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