]>
Commit | Line | Data |
---|---|---|
832b75ed GG |
1 | /* |
2 | * utility.h | |
3 | * | |
a86ec89e | 4 | * Home page of code is: http://www.smartmontools.org |
832b75ed | 5 | * |
a86ec89e | 6 | * Copyright (C) 2002-11 Bruce Allen |
ff28b140 | 7 | * Copyright (C) 2008-18 Christian Franke |
832b75ed GG |
8 | * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> |
9 | * | |
ff28b140 | 10 | * SPDX-License-Identifier: GPL-2.0-or-later |
832b75ed GG |
11 | */ |
12 | ||
13 | #ifndef UTILITY_H_ | |
14 | #define UTILITY_H_ | |
15 | ||
ff28b140 | 16 | #define UTILITY_H_CVSID "$Id: utility.h 4848 2018-12-05 18:30:46Z chrfranke $" |
832b75ed | 17 | |
ff28b140 | 18 | #include <float.h> // *DBL_MANT_DIG |
832b75ed | 19 | #include <time.h> |
2127e193 | 20 | #include <stdarg.h> |
ff28b140 | 21 | #include <stdint.h> |
2127e193 GI |
22 | #include <stdio.h> |
23 | #include <string.h> | |
24 | #include <string> | |
25 | ||
ff28b140 TL |
26 | #include <sys/types.h> // for regex.h (according to POSIX) |
27 | #ifdef WITH_CXX11_REGEX | |
28 | #include <regex> | |
29 | #else | |
30 | #include <regex.h> | |
31 | #endif | |
32 | ||
d008864d GI |
33 | #ifndef __GNUC__ |
34 | #define __attribute_format_printf(x, y) /**/ | |
35 | #elif defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO | |
36 | // Check format of __mingw_*printf() instead of MSVCRT.DLL:*printf() | |
37 | #define __attribute_format_printf(x, y) __attribute__((format (gnu_printf, x, y))) | |
38 | #define HAVE_WORKING_SNPRINTF 1 | |
39 | #else | |
40 | #define __attribute_format_printf(x, y) __attribute__((format (printf, x, y))) | |
2127e193 GI |
41 | #endif |
42 | ||
43 | // Make version information string | |
44 | std::string format_version_info(const char * prog_name, bool full = false); | |
45 | ||
ff28b140 | 46 | // return (v)sprintf() formatted std::string |
2127e193 | 47 | std::string strprintf(const char * fmt, ...) |
d008864d | 48 | __attribute_format_printf(1, 2); |
2127e193 | 49 | std::string vstrprintf(const char * fmt, va_list ap); |
832b75ed | 50 | |
f4e463df GI |
51 | // Return true if STR starts with PREFIX |
52 | inline bool str_starts_with(const char * str, const char * prefix) | |
53 | { return !strncmp(str, prefix, strlen(prefix)); } | |
54 | ||
55 | inline bool str_starts_with(const std::string & str, const char * prefix) | |
56 | { return !strncmp(str.c_str(), prefix, strlen(prefix)); } | |
57 | ||
832b75ed GG |
58 | #ifndef HAVE_WORKING_SNPRINTF |
59 | // Substitute by safe replacement functions | |
2127e193 | 60 | int safe_snprintf(char *buf, int size, const char *fmt, ...) |
d008864d | 61 | __attribute_format_printf(3, 4); |
832b75ed GG |
62 | int safe_vsnprintf(char *buf, int size, const char *fmt, va_list ap); |
63 | #define snprintf safe_snprintf | |
64 | #define vsnprintf safe_vsnprintf | |
65 | #endif | |
66 | ||
ff28b140 TL |
67 | // Utility function prints date and time and timezone into a character |
68 | // buffer of length 64. All the fuss is needed to get the | |
832b75ed GG |
69 | // right timezone info (sigh). |
70 | #define DATEANDEPOCHLEN 64 | |
ff28b140 | 71 | void dateandtimezoneepoch(char (& buffer)[DATEANDEPOCHLEN], time_t tval); |
832b75ed | 72 | |
832b75ed GG |
73 | // like printf() except that we can control it better. Note -- |
74 | // although the prototype is given here in utility.h, the function | |
75 | // itself is defined differently in smartctl and smartd. So the | |
76 | // function definition(s) are in smartd.c and in smartctl.c. | |
4d59bff9 | 77 | void pout(const char *fmt, ...) |
d008864d | 78 | __attribute_format_printf(1, 2); |
832b75ed GG |
79 | |
80 | // replacement for perror() with redirected output. | |
81 | void syserror(const char *message); | |
82 | ||
832b75ed | 83 | // Function for processing -t selective... option in smartctl |
a37e7145 | 84 | int split_selective_arg(char *s, uint64_t *start, uint64_t *stop, int *mode); |
832b75ed | 85 | |
e9583e0c GI |
86 | // Compile time check of byte ordering |
87 | // (inline const function allows compiler to remove dead code) | |
88 | inline bool isbigendian() | |
89 | { | |
90 | #ifdef WORDS_BIGENDIAN | |
91 | return true; | |
92 | #else | |
93 | return false; | |
94 | #endif | |
95 | } | |
96 | ||
ff28b140 TL |
97 | void swap2(char *location); |
98 | void swap4(char *location); | |
99 | void swap8(char *location); | |
100 | // Typesafe variants using overloading | |
101 | inline void swapx(unsigned short * p) | |
102 | { swap2((char*)p); } | |
103 | inline void swapx(unsigned int * p) | |
104 | { swap4((char*)p); } | |
105 | inline void swapx(uint64_t * p) | |
106 | { swap8((char*)p); } | |
107 | ||
d2e702cf GI |
108 | // Runtime check of ./configure result, throws on error. |
109 | void check_config(); | |
832b75ed GG |
110 | |
111 | // This value follows the peripheral device type value as defined in | |
112 | // SCSI Primary Commands, ANSI INCITS 301:1997. It is also used in | |
113 | // the ATA standard for packet devices to define the device type. | |
114 | const char *packetdevicetype(int type); | |
115 | ||
2127e193 GI |
116 | // returns true if any of the n bytes are nonzero, else zero. |
117 | bool nonempty(const void * data, int size); | |
832b75ed GG |
118 | |
119 | // needed to fix glibc bug | |
120 | void FixGlibcTimeZoneBug(); | |
121 | ||
a86ec89e GI |
122 | // Copy not null terminated char array to null terminated string. |
123 | // Replace non-ascii characters. Remove leading and trailing blanks. | |
124 | const char * format_char_array(char * str, int strsize, const char * chr, int chrsize); | |
125 | ||
126 | // Version for fixed size buffers. | |
127 | template<size_t STRSIZE, size_t CHRSIZE> | |
128 | inline const char * format_char_array(char (& str)[STRSIZE], const char (& chr)[CHRSIZE]) | |
129 | { return format_char_array(str, (int)STRSIZE, chr, (int)CHRSIZE); } | |
130 | ||
a7e8ffec GI |
131 | // Format integer with thousands separator |
132 | const char * format_with_thousands_sep(char * str, int strsize, uint64_t val, | |
133 | const char * thousands_sep = 0); | |
134 | ||
135 | // Format capacity with SI prefixes | |
136 | const char * format_capacity(char * str, int strsize, uint64_t val, | |
137 | const char * decimal_point = 0); | |
138 | ||
2127e193 GI |
139 | // Wrapper class for a raw data buffer |
140 | class raw_buffer | |
141 | { | |
142 | public: | |
143 | explicit raw_buffer(unsigned sz, unsigned char val = 0) | |
144 | : m_data(new unsigned char[sz]), | |
145 | m_size(sz) | |
146 | { memset(m_data, val, m_size); } | |
147 | ||
148 | ~raw_buffer() | |
149 | { delete [] m_data; } | |
150 | ||
151 | unsigned size() const | |
152 | { return m_size; } | |
153 | ||
154 | unsigned char * data() | |
155 | { return m_data; } | |
156 | const unsigned char * data() const | |
157 | { return m_data; } | |
158 | ||
159 | private: | |
160 | unsigned char * m_data; | |
161 | unsigned m_size; | |
162 | ||
163 | raw_buffer(const raw_buffer &); | |
164 | void operator=(const raw_buffer &); | |
165 | }; | |
166 | ||
167 | /// Wrapper class for FILE *. | |
168 | class stdio_file | |
169 | { | |
170 | public: | |
171 | explicit stdio_file(FILE * f = 0, bool owner = false) | |
172 | : m_file(f), m_owner(owner) { } | |
173 | ||
174 | stdio_file(const char * name, const char * mode) | |
175 | : m_file(fopen(name, mode)), m_owner(true) { } | |
176 | ||
177 | ~stdio_file() | |
178 | { | |
179 | if (m_file && m_owner) | |
180 | fclose(m_file); | |
181 | } | |
182 | ||
183 | bool open(const char * name, const char * mode) | |
184 | { | |
a86ec89e GI |
185 | if (m_file && m_owner) |
186 | fclose(m_file); | |
2127e193 GI |
187 | m_file = fopen(name, mode); |
188 | m_owner = true; | |
189 | return !!m_file; | |
190 | } | |
191 | ||
192 | void open(FILE * f, bool owner = false) | |
193 | { | |
a86ec89e GI |
194 | if (m_file && m_owner) |
195 | fclose(m_file); | |
2127e193 GI |
196 | m_file = f; |
197 | m_owner = owner; | |
198 | } | |
199 | ||
200 | bool close() | |
201 | { | |
202 | if (!m_file) | |
203 | return true; | |
204 | bool ok = !ferror(m_file); | |
205 | if (fclose(m_file)) | |
206 | ok = false; | |
207 | m_file = 0; | |
208 | return ok; | |
209 | } | |
210 | ||
211 | operator FILE * () | |
212 | { return m_file; } | |
213 | ||
214 | bool operator!() const | |
215 | { return !m_file; } | |
216 | ||
217 | private: | |
218 | FILE * m_file; | |
219 | bool m_owner; | |
220 | ||
221 | stdio_file(const stdio_file &); | |
222 | void operator=(const stdio_file &); | |
223 | }; | |
224 | ||
ff28b140 | 225 | /// Wrapper class for POSIX regex(3) or std::regex |
2127e193 GI |
226 | /// Supports copy & assignment and is compatible with STL containers. |
227 | class regular_expression | |
228 | { | |
229 | public: | |
230 | // Construction & assignment | |
ff28b140 TL |
231 | #ifdef WITH_CXX11_REGEX |
232 | regular_expression() = default; | |
2127e193 | 233 | |
ff28b140 TL |
234 | #else |
235 | regular_expression(); | |
2127e193 GI |
236 | |
237 | ~regular_expression(); | |
238 | ||
239 | regular_expression(const regular_expression & x); | |
240 | ||
241 | regular_expression & operator=(const regular_expression & x); | |
ff28b140 TL |
242 | #endif |
243 | ||
244 | /// Construct with pattern, throw on error. | |
245 | explicit regular_expression(const char * pattern); | |
2127e193 GI |
246 | |
247 | /// Set and compile new pattern, return false on error. | |
ff28b140 | 248 | bool compile(const char * pattern); |
2127e193 GI |
249 | |
250 | // Get pattern from last compile(). | |
251 | const char * get_pattern() const | |
252 | { return m_pattern.c_str(); } | |
253 | ||
254 | /// Get error message from last compile(). | |
255 | const char * get_errmsg() const | |
256 | { return m_errmsg.c_str(); } | |
257 | ||
258 | // Return true if pattern is not set or bad. | |
259 | bool empty() const | |
260 | { return (m_pattern.empty() || !m_errmsg.empty()); } | |
261 | ||
2127e193 | 262 | /// Return true if full string matches pattern |
ff28b140 | 263 | bool full_match(const char * str) const; |
2127e193 | 264 | |
ff28b140 TL |
265 | #ifdef WITH_CXX11_REGEX |
266 | struct match_range { int rm_so, rm_eo; }; | |
267 | #else | |
268 | typedef regmatch_t match_range; | |
269 | #endif | |
270 | ||
271 | /// Return true if substring matches pattern, fill match_range array. | |
272 | bool execute(const char * str, unsigned nmatch, match_range * pmatch) const; | |
2127e193 GI |
273 | |
274 | private: | |
275 | std::string m_pattern; | |
2127e193 GI |
276 | std::string m_errmsg; |
277 | ||
ff28b140 TL |
278 | #ifdef WITH_CXX11_REGEX |
279 | std::regex m_regex; | |
280 | #else | |
281 | regex_t m_regex_buf; | |
2127e193 | 282 | void free_buf(); |
ff28b140 TL |
283 | void copy_buf(const regular_expression & x); |
284 | #endif | |
285 | ||
2127e193 GI |
286 | bool compile(); |
287 | }; | |
832b75ed | 288 | |
ff28b140 TL |
289 | // 128-bit unsigned integer to string conversion. |
290 | // Provides full integer precision if compiler supports '__int128'. | |
291 | // Otherwise precision depends on supported floating point data types. | |
292 | ||
293 | #if defined(HAVE_LONG_DOUBLE_WIDER) && \ | |
294 | (!defined(__MINGW32__) || defined(__USE_MINGW_ANSI_STDIO)) | |
295 | // MinGW 'long double' type does not work with MSVCRT *printf() | |
296 | #define HAVE_LONG_DOUBLE_WIDER_PRINTF 1 | |
297 | #else | |
298 | #undef HAVE_LONG_DOUBLE_WIDER_PRINTF | |
299 | #endif | |
300 | ||
301 | // Return #bits precision provided by uint128_hilo_to_str(). | |
302 | inline int uint128_to_str_precision_bits() | |
303 | { | |
304 | #if defined(HAVE___INT128) | |
305 | return 128; | |
306 | #elif defined(HAVE_LONG_DOUBLE_WIDER_PRINTF) | |
307 | return LDBL_MANT_DIG; | |
308 | #else | |
309 | return DBL_MANT_DIG; | |
310 | #endif | |
311 | } | |
312 | ||
313 | // Convert 128-bit unsigned integer provided as two 64-bit halves to a string. | |
314 | const char * uint128_hilo_to_str(char * str, int strsize, uint64_t value_hi, uint64_t value_lo); | |
315 | ||
316 | // Version for fixed size buffers. | |
317 | template <size_t SIZE> | |
318 | inline const char * uint128_hilo_to_str(char (& str)[SIZE], uint64_t value_hi, uint64_t value_lo) | |
319 | { return uint128_hilo_to_str(str, (int)SIZE, value_hi, value_lo); } | |
320 | ||
e9583e0c GI |
321 | #ifdef _WIN32 |
322 | // Get exe directory | |
323 | //(implemented in os_win32.cpp) | |
324 | std::string get_exe_dir(); | |
325 | #endif | |
326 | ||
327 | ||
2127e193 | 328 | #ifdef OLD_INTERFACE |
cfbba5b9 | 329 | // remaining controller types in old interface modules |
832b75ed GG |
330 | #define CONTROLLER_UNKNOWN 0x00 |
331 | #define CONTROLLER_ATA 0x01 | |
332 | #define CONTROLLER_SCSI 0x02 | |
2127e193 | 333 | #endif |
832b75ed GG |
334 | |
335 | #endif |