]>
Commit | Line | Data |
---|---|---|
832b75ed GG |
1 | /* |
2 | * utility.h | |
3 | * | |
6b80b4d2 | 4 | * Home page of code is: http://www.smartmontools.org |
832b75ed | 5 | * |
6b80b4d2 JD |
6 | * Copyright (C) 2002-11 Bruce Allen |
7 | * Copyright (C) 2008-15 Christian Franke | |
832b75ed GG |
8 | * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> |
9 | * | |
10 | * This program is free software; you can redistribute it and/or modify | |
11 | * it under the terms of the GNU General Public License as published by | |
12 | * the Free Software Foundation; either version 2, or (at your option) | |
13 | * any later version. | |
14 | * | |
15 | * You should have received a copy of the GNU General Public License | |
ee38a438 | 16 | * (for example COPYING); If not, see <http://www.gnu.org/licenses/>. |
832b75ed GG |
17 | * |
18 | * This code was originally developed as a Senior Thesis by Michael Cornwell | |
19 | * at the Concurrent Systems Laboratory (now part of the Storage Systems | |
20 | * Research Center), Jack Baskin School of Engineering, University of | |
21 | * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ | |
22 | * | |
23 | */ | |
24 | ||
25 | #ifndef UTILITY_H_ | |
26 | #define UTILITY_H_ | |
27 | ||
6b80b4d2 | 28 | #define UTILITY_H_CVSID "$Id: utility.h 4145 2015-10-17 12:01:38Z chrfranke $" |
832b75ed GG |
29 | |
30 | #include <time.h> | |
31 | #include <sys/types.h> // for regex.h (according to POSIX) | |
32 | #include <regex.h> | |
2127e193 GI |
33 | #include <stdarg.h> |
34 | #include <stdio.h> | |
35 | #include <string.h> | |
36 | #include <string> | |
37 | ||
d008864d GI |
38 | #ifndef __GNUC__ |
39 | #define __attribute_format_printf(x, y) /**/ | |
40 | #elif defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO | |
41 | // Check format of __mingw_*printf() instead of MSVCRT.DLL:*printf() | |
42 | #define __attribute_format_printf(x, y) __attribute__((format (gnu_printf, x, y))) | |
43 | #define HAVE_WORKING_SNPRINTF 1 | |
44 | #else | |
45 | #define __attribute_format_printf(x, y) __attribute__((format (printf, x, y))) | |
2127e193 GI |
46 | #endif |
47 | ||
48 | // Make version information string | |
49 | std::string format_version_info(const char * prog_name, bool full = false); | |
50 | ||
51 | // return (v)sprintf() formated std::string | |
52 | std::string strprintf(const char * fmt, ...) | |
d008864d | 53 | __attribute_format_printf(1, 2); |
2127e193 | 54 | std::string vstrprintf(const char * fmt, va_list ap); |
832b75ed | 55 | |
f4e463df GI |
56 | // Return true if STR starts with PREFIX |
57 | inline bool str_starts_with(const char * str, const char * prefix) | |
58 | { return !strncmp(str, prefix, strlen(prefix)); } | |
59 | ||
60 | inline bool str_starts_with(const std::string & str, const char * prefix) | |
61 | { return !strncmp(str.c_str(), prefix, strlen(prefix)); } | |
62 | ||
832b75ed GG |
63 | #ifndef HAVE_WORKING_SNPRINTF |
64 | // Substitute by safe replacement functions | |
2127e193 | 65 | int safe_snprintf(char *buf, int size, const char *fmt, ...) |
d008864d | 66 | __attribute_format_printf(3, 4); |
832b75ed GG |
67 | int safe_vsnprintf(char *buf, int size, const char *fmt, va_list ap); |
68 | #define snprintf safe_snprintf | |
69 | #define vsnprintf safe_vsnprintf | |
70 | #endif | |
71 | ||
2127e193 GI |
72 | #ifndef HAVE_STRTOULL |
73 | // Replacement for missing strtoull() (Linux with libc < 6, MSVC) | |
74 | uint64_t strtoull(const char * p, char * * endp, int base); | |
75 | #endif | |
76 | ||
832b75ed GG |
77 | // Utility function prints current date and time and timezone into a |
78 | // character buffer of length>=64. All the fuss is needed to get the | |
79 | // right timezone info (sigh). | |
80 | #define DATEANDEPOCHLEN 64 | |
81 | void dateandtimezone(char *buffer); | |
82 | // Same, but for time defined by epoch tval | |
83 | void dateandtimezoneepoch(char *buffer, time_t tval); | |
84 | ||
832b75ed GG |
85 | // like printf() except that we can control it better. Note -- |
86 | // although the prototype is given here in utility.h, the function | |
87 | // itself is defined differently in smartctl and smartd. So the | |
88 | // function definition(s) are in smartd.c and in smartctl.c. | |
4d59bff9 | 89 | void pout(const char *fmt, ...) |
d008864d | 90 | __attribute_format_printf(1, 2); |
832b75ed GG |
91 | |
92 | // replacement for perror() with redirected output. | |
93 | void syserror(const char *message); | |
94 | ||
832b75ed GG |
95 | // Function for processing -r option in smartctl and smartd |
96 | int split_report_arg(char *s, int *i); | |
a37e7145 | 97 | |
832b75ed | 98 | // Function for processing -t selective... option in smartctl |
a37e7145 | 99 | int split_selective_arg(char *s, uint64_t *start, uint64_t *stop, int *mode); |
832b75ed | 100 | |
2127e193 GI |
101 | // Replacement for exit(status) |
102 | // (exit is not compatible with C++ destructors) | |
103 | #define EXIT(status) { throw (int)(status); } | |
832b75ed GG |
104 | |
105 | ||
2127e193 | 106 | #ifdef OLD_INTERFACE |
832b75ed | 107 | |
832b75ed | 108 | // Utility function to free memory |
293b5ab8 | 109 | void *FreeNonZero(void* address, int size, int whatline, const char* file); |
832b75ed GG |
110 | |
111 | // A custom version of strdup() that keeps track of how much memory is | |
112 | // being allocated. If mustexist is set, it also throws an error if we | |
113 | // try to duplicate a NULL string. | |
a37e7145 | 114 | char *CustomStrDup(const char *ptr, int mustexist, int whatline, const char* file); |
832b75ed | 115 | |
2127e193 GI |
116 | #endif // OLD_INTERFACE |
117 | ||
e9583e0c GI |
118 | // Compile time check of byte ordering |
119 | // (inline const function allows compiler to remove dead code) | |
120 | inline bool isbigendian() | |
121 | { | |
122 | #ifdef WORDS_BIGENDIAN | |
123 | return true; | |
124 | #else | |
125 | return false; | |
126 | #endif | |
127 | } | |
128 | ||
d2e702cf GI |
129 | // Runtime check of ./configure result, throws on error. |
130 | void check_config(); | |
832b75ed GG |
131 | |
132 | // This value follows the peripheral device type value as defined in | |
133 | // SCSI Primary Commands, ANSI INCITS 301:1997. It is also used in | |
134 | // the ATA standard for packet devices to define the device type. | |
135 | const char *packetdevicetype(int type); | |
136 | ||
2127e193 GI |
137 | // returns true if any of the n bytes are nonzero, else zero. |
138 | bool nonempty(const void * data, int size); | |
832b75ed GG |
139 | |
140 | // needed to fix glibc bug | |
141 | void FixGlibcTimeZoneBug(); | |
142 | ||
a7e8ffec GI |
143 | // Format integer with thousands separator |
144 | const char * format_with_thousands_sep(char * str, int strsize, uint64_t val, | |
145 | const char * thousands_sep = 0); | |
146 | ||
147 | // Format capacity with SI prefixes | |
148 | const char * format_capacity(char * str, int strsize, uint64_t val, | |
149 | const char * decimal_point = 0); | |
150 | ||
2127e193 GI |
151 | // Wrapper class for a raw data buffer |
152 | class raw_buffer | |
153 | { | |
154 | public: | |
155 | explicit raw_buffer(unsigned sz, unsigned char val = 0) | |
156 | : m_data(new unsigned char[sz]), | |
157 | m_size(sz) | |
158 | { memset(m_data, val, m_size); } | |
159 | ||
160 | ~raw_buffer() | |
161 | { delete [] m_data; } | |
162 | ||
163 | unsigned size() const | |
164 | { return m_size; } | |
165 | ||
166 | unsigned char * data() | |
167 | { return m_data; } | |
168 | const unsigned char * data() const | |
169 | { return m_data; } | |
170 | ||
171 | private: | |
172 | unsigned char * m_data; | |
173 | unsigned m_size; | |
174 | ||
175 | raw_buffer(const raw_buffer &); | |
176 | void operator=(const raw_buffer &); | |
177 | }; | |
178 | ||
179 | /// Wrapper class for FILE *. | |
180 | class stdio_file | |
181 | { | |
182 | public: | |
183 | explicit stdio_file(FILE * f = 0, bool owner = false) | |
184 | : m_file(f), m_owner(owner) { } | |
185 | ||
186 | stdio_file(const char * name, const char * mode) | |
187 | : m_file(fopen(name, mode)), m_owner(true) { } | |
188 | ||
189 | ~stdio_file() | |
190 | { | |
191 | if (m_file && m_owner) | |
192 | fclose(m_file); | |
193 | } | |
194 | ||
195 | bool open(const char * name, const char * mode) | |
196 | { | |
6b80b4d2 JD |
197 | if (m_file && m_owner) |
198 | fclose(m_file); | |
2127e193 GI |
199 | m_file = fopen(name, mode); |
200 | m_owner = true; | |
201 | return !!m_file; | |
202 | } | |
203 | ||
204 | void open(FILE * f, bool owner = false) | |
205 | { | |
6b80b4d2 JD |
206 | if (m_file && m_owner) |
207 | fclose(m_file); | |
2127e193 GI |
208 | m_file = f; |
209 | m_owner = owner; | |
210 | } | |
211 | ||
212 | bool close() | |
213 | { | |
214 | if (!m_file) | |
215 | return true; | |
216 | bool ok = !ferror(m_file); | |
217 | if (fclose(m_file)) | |
218 | ok = false; | |
219 | m_file = 0; | |
220 | return ok; | |
221 | } | |
222 | ||
223 | operator FILE * () | |
224 | { return m_file; } | |
225 | ||
226 | bool operator!() const | |
227 | { return !m_file; } | |
228 | ||
229 | private: | |
230 | FILE * m_file; | |
231 | bool m_owner; | |
232 | ||
233 | stdio_file(const stdio_file &); | |
234 | void operator=(const stdio_file &); | |
235 | }; | |
236 | ||
237 | /// Wrapper class for regex(3). | |
238 | /// Supports copy & assignment and is compatible with STL containers. | |
239 | class regular_expression | |
240 | { | |
241 | public: | |
242 | // Construction & assignment | |
243 | regular_expression(); | |
244 | ||
cfbba5b9 GI |
245 | regular_expression(const char * pattern, int flags, |
246 | bool throw_on_error = true); | |
2127e193 GI |
247 | |
248 | ~regular_expression(); | |
249 | ||
250 | regular_expression(const regular_expression & x); | |
251 | ||
252 | regular_expression & operator=(const regular_expression & x); | |
253 | ||
254 | /// Set and compile new pattern, return false on error. | |
255 | bool compile(const char * pattern, int flags); | |
256 | ||
257 | // Get pattern from last compile(). | |
258 | const char * get_pattern() const | |
259 | { return m_pattern.c_str(); } | |
260 | ||
261 | /// Get error message from last compile(). | |
262 | const char * get_errmsg() const | |
263 | { return m_errmsg.c_str(); } | |
264 | ||
265 | // Return true if pattern is not set or bad. | |
266 | bool empty() const | |
267 | { return (m_pattern.empty() || !m_errmsg.empty()); } | |
268 | ||
269 | /// Return true if substring matches pattern | |
270 | bool match(const char * str, int flags = 0) const | |
271 | { return !regexec(&m_regex_buf, str, 0, (regmatch_t*)0, flags); } | |
272 | ||
273 | /// Return true if full string matches pattern | |
274 | bool full_match(const char * str, int flags = 0) const | |
275 | { | |
276 | regmatch_t range; | |
277 | return ( !regexec(&m_regex_buf, str, 1, &range, flags) | |
278 | && range.rm_so == 0 && range.rm_eo == (int)strlen(str)); | |
279 | } | |
280 | ||
281 | /// Return true if substring matches pattern, fill regmatch_t array. | |
282 | bool execute(const char * str, unsigned nmatch, regmatch_t * pmatch, int flags = 0) const | |
283 | { return !regexec(&m_regex_buf, str, nmatch, pmatch, flags); } | |
284 | ||
285 | private: | |
286 | std::string m_pattern; | |
287 | int m_flags; | |
288 | regex_t m_regex_buf; | |
289 | std::string m_errmsg; | |
290 | ||
291 | void free_buf(); | |
292 | void copy(const regular_expression & x); | |
293 | bool compile(); | |
294 | }; | |
832b75ed | 295 | |
e9583e0c GI |
296 | #ifdef _WIN32 |
297 | // Get exe directory | |
298 | //(implemented in os_win32.cpp) | |
299 | std::string get_exe_dir(); | |
300 | #endif | |
301 | ||
302 | ||
2127e193 | 303 | #ifdef OLD_INTERFACE |
cfbba5b9 | 304 | // remaining controller types in old interface modules |
832b75ed GG |
305 | #define CONTROLLER_UNKNOWN 0x00 |
306 | #define CONTROLLER_ATA 0x01 | |
307 | #define CONTROLLER_SCSI 0x02 | |
2127e193 | 308 | #endif |
832b75ed GG |
309 | |
310 | #endif | |
a23d5117 | 311 |