4 * Home page of code is: http://www.smartmontools.org
6 * Copyright (C) 2002-11 Bruce Allen
7 * Copyright (C) 2008-18 Christian Franke
8 * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
10 * SPDX-License-Identifier: GPL-2.0-or-later
16 #define UTILITY_H_CVSID "$Id: utility.h 4848 2018-12-05 18:30:46Z chrfranke $"
18 #include <float.h> // *DBL_MANT_DIG
26 #include <sys/types.h> // for regex.h (according to POSIX)
27 #ifdef WITH_CXX11_REGEX
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
40 #define __attribute_format_printf(x, y) __attribute__((format (printf, x, y)))
43 // Make version information string
44 std::string
format_version_info(const char * prog_name
, bool full
= false);
46 // return (v)sprintf() formatted std::string
47 std::string
strprintf(const char * fmt
, ...)
48 __attribute_format_printf(1, 2);
49 std::string
vstrprintf(const char * fmt
, va_list ap
);
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
)); }
55 inline bool str_starts_with(const std::string
& str
, const char * prefix
)
56 { return !strncmp(str
.c_str(), prefix
, strlen(prefix
)); }
58 #ifndef HAVE_WORKING_SNPRINTF
59 // Substitute by safe replacement functions
60 int safe_snprintf(char *buf
, int size
, const char *fmt
, ...)
61 __attribute_format_printf(3, 4);
62 int safe_vsnprintf(char *buf
, int size
, const char *fmt
, va_list ap
);
63 #define snprintf safe_snprintf
64 #define vsnprintf safe_vsnprintf
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
69 // right timezone info (sigh).
70 #define DATEANDEPOCHLEN 64
71 void dateandtimezoneepoch(char (& buffer
)[DATEANDEPOCHLEN
], time_t tval
);
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.
77 void pout(const char *fmt
, ...)
78 __attribute_format_printf(1, 2);
80 // replacement for perror() with redirected output.
81 void syserror(const char *message
);
83 // Function for processing -t selective... option in smartctl
84 int split_selective_arg(char *s
, uint64_t *start
, uint64_t *stop
, int *mode
);
86 // Compile time check of byte ordering
87 // (inline const function allows compiler to remove dead code)
88 inline bool isbigendian()
90 #ifdef WORDS_BIGENDIAN
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
)
103 inline void swapx(unsigned int * p
)
105 inline void swapx(uint64_t * p
)
108 // Runtime check of ./configure result, throws on error.
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
);
116 // returns true if any of the n bytes are nonzero, else zero.
117 bool nonempty(const void * data
, int size
);
119 // needed to fix glibc bug
120 void FixGlibcTimeZoneBug();
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
);
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
); }
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);
135 // Format capacity with SI prefixes
136 const char * format_capacity(char * str
, int strsize
, uint64_t val
,
137 const char * decimal_point
= 0);
139 // Wrapper class for a raw data buffer
143 explicit raw_buffer(unsigned sz
, unsigned char val
= 0)
144 : m_data(new unsigned char[sz
]),
146 { memset(m_data
, val
, m_size
); }
149 { delete [] m_data
; }
151 unsigned size() const
154 unsigned char * data()
156 const unsigned char * data() const
160 unsigned char * m_data
;
163 raw_buffer(const raw_buffer
&);
164 void operator=(const raw_buffer
&);
167 /// Wrapper class for FILE *.
171 explicit stdio_file(FILE * f
= 0, bool owner
= false)
172 : m_file(f
), m_owner(owner
) { }
174 stdio_file(const char * name
, const char * mode
)
175 : m_file(fopen(name
, mode
)), m_owner(true) { }
179 if (m_file
&& m_owner
)
183 bool open(const char * name
, const char * mode
)
185 if (m_file
&& m_owner
)
187 m_file
= fopen(name
, mode
);
192 void open(FILE * f
, bool owner
= false)
194 if (m_file
&& m_owner
)
204 bool ok
= !ferror(m_file
);
214 bool operator!() const
221 stdio_file(const stdio_file
&);
222 void operator=(const stdio_file
&);
225 /// Wrapper class for POSIX regex(3) or std::regex
226 /// Supports copy & assignment and is compatible with STL containers.
227 class regular_expression
230 // Construction & assignment
231 #ifdef WITH_CXX11_REGEX
232 regular_expression() = default;
235 regular_expression();
237 ~regular_expression();
239 regular_expression(const regular_expression
& x
);
241 regular_expression
& operator=(const regular_expression
& x
);
244 /// Construct with pattern, throw on error.
245 explicit regular_expression(const char * pattern
);
247 /// Set and compile new pattern, return false on error.
248 bool compile(const char * pattern
);
250 // Get pattern from last compile().
251 const char * get_pattern() const
252 { return m_pattern
.c_str(); }
254 /// Get error message from last compile().
255 const char * get_errmsg() const
256 { return m_errmsg
.c_str(); }
258 // Return true if pattern is not set or bad.
260 { return (m_pattern
.empty() || !m_errmsg
.empty()); }
262 /// Return true if full string matches pattern
263 bool full_match(const char * str
) const;
265 #ifdef WITH_CXX11_REGEX
266 struct match_range
{ int rm_so
, rm_eo
; };
268 typedef regmatch_t match_range
;
271 /// Return true if substring matches pattern, fill match_range array.
272 bool execute(const char * str
, unsigned nmatch
, match_range
* pmatch
) const;
275 std::string m_pattern
;
276 std::string m_errmsg
;
278 #ifdef WITH_CXX11_REGEX
283 void copy_buf(const regular_expression
& x
);
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.
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
298 #undef HAVE_LONG_DOUBLE_WIDER_PRINTF
301 // Return #bits precision provided by uint128_hilo_to_str().
302 inline int uint128_to_str_precision_bits()
304 #if defined(HAVE___INT128)
306 #elif defined(HAVE_LONG_DOUBLE_WIDER_PRINTF)
307 return LDBL_MANT_DIG
;
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
);
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
); }
323 //(implemented in os_win32.cpp)
324 std::string
get_exe_dir();
329 // remaining controller types in old interface modules
330 #define CONTROLLER_UNKNOWN 0x00
331 #define CONTROLLER_ATA 0x01
332 #define CONTROLLER_SCSI 0x02