]> git.proxmox.com Git - mirror_smartmontools-debian.git/blame - utility.h
import smartmontools 7.0
[mirror_smartmontools-debian.git] / utility.h
CommitLineData
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
44std::string format_version_info(const char * prog_name, bool full = false);
45
ff28b140 46// return (v)sprintf() formatted std::string
2127e193 47std::string strprintf(const char * fmt, ...)
d008864d 48 __attribute_format_printf(1, 2);
2127e193 49std::string vstrprintf(const char * fmt, va_list ap);
832b75ed 50
f4e463df
GI
51// Return true if STR starts with PREFIX
52inline bool str_starts_with(const char * str, const char * prefix)
53 { return !strncmp(str, prefix, strlen(prefix)); }
54
55inline 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 60int safe_snprintf(char *buf, int size, const char *fmt, ...)
d008864d 61 __attribute_format_printf(3, 4);
832b75ed
GG
62int 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 71void 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 77void pout(const char *fmt, ...)
d008864d 78 __attribute_format_printf(1, 2);
832b75ed
GG
79
80// replacement for perror() with redirected output.
81void syserror(const char *message);
82
832b75ed 83// Function for processing -t selective... option in smartctl
a37e7145 84int 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)
88inline bool isbigendian()
89{
90#ifdef WORDS_BIGENDIAN
91 return true;
92#else
93 return false;
94#endif
95}
96
ff28b140
TL
97void swap2(char *location);
98void swap4(char *location);
99void swap8(char *location);
100// Typesafe variants using overloading
101inline void swapx(unsigned short * p)
102 { swap2((char*)p); }
103inline void swapx(unsigned int * p)
104 { swap4((char*)p); }
105inline void swapx(uint64_t * p)
106 { swap8((char*)p); }
107
d2e702cf
GI
108// Runtime check of ./configure result, throws on error.
109void 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.
114const char *packetdevicetype(int type);
115
2127e193
GI
116// returns true if any of the n bytes are nonzero, else zero.
117bool nonempty(const void * data, int size);
832b75ed
GG
118
119// needed to fix glibc bug
120void 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.
124const char * format_char_array(char * str, int strsize, const char * chr, int chrsize);
125
126// Version for fixed size buffers.
127template<size_t STRSIZE, size_t CHRSIZE>
128inline 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
132const 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
136const 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
140class raw_buffer
141{
142public:
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
159private:
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 *.
168class stdio_file
169{
170public:
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
217private:
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.
227class regular_expression
228{
229public:
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
274private:
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().
302inline 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.
314const char * uint128_hilo_to_str(char * str, int strsize, uint64_t value_hi, uint64_t value_lo);
315
316// Version for fixed size buffers.
317template <size_t SIZE>
318inline 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)
324std::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