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