1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
|
/*
* utility.h
*
* Home page of code is: http://www.smartmontools.org
*
* Copyright (C) 2002-11 Bruce Allen
* Copyright (C) 2008-16 Christian Franke
* Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* You should have received a copy of the GNU General Public License
* (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
*
* This code was originally developed as a Senior Thesis by Michael Cornwell
* at the Concurrent Systems Laboratory (now part of the Storage Systems
* Research Center), Jack Baskin School of Engineering, University of
* California, Santa Cruz. http://ssrc.soe.ucsc.edu/
*
*/
#ifndef UTILITY_H_
#define UTILITY_H_
#define UTILITY_H_CVSID "$Id: utility.h 4309 2016-04-24 14:59:15Z chrfranke $"
#include <time.h>
#include <sys/types.h> // for regex.h (according to POSIX)
#include <regex.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include <string>
#ifndef __GNUC__
#define __attribute_format_printf(x, y) /**/
#elif defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO
// Check format of __mingw_*printf() instead of MSVCRT.DLL:*printf()
#define __attribute_format_printf(x, y) __attribute__((format (gnu_printf, x, y)))
#define HAVE_WORKING_SNPRINTF 1
#else
#define __attribute_format_printf(x, y) __attribute__((format (printf, x, y)))
#endif
// Make version information string
std::string format_version_info(const char * prog_name, bool full = false);
// return (v)sprintf() formated std::string
std::string strprintf(const char * fmt, ...)
__attribute_format_printf(1, 2);
std::string vstrprintf(const char * fmt, va_list ap);
// Return true if STR starts with PREFIX
inline bool str_starts_with(const char * str, const char * prefix)
{ return !strncmp(str, prefix, strlen(prefix)); }
inline bool str_starts_with(const std::string & str, const char * prefix)
{ return !strncmp(str.c_str(), prefix, strlen(prefix)); }
#ifndef HAVE_WORKING_SNPRINTF
// Substitute by safe replacement functions
int safe_snprintf(char *buf, int size, const char *fmt, ...)
__attribute_format_printf(3, 4);
int safe_vsnprintf(char *buf, int size, const char *fmt, va_list ap);
#define snprintf safe_snprintf
#define vsnprintf safe_vsnprintf
#endif
#ifndef HAVE_STRTOULL
// Replacement for missing strtoull() (Linux with libc < 6, MSVC)
uint64_t strtoull(const char * p, char * * endp, int base);
#endif
// Utility function prints current date and time and timezone into a
// character buffer of length>=64. All the fuss is needed to get the
// right timezone info (sigh).
#define DATEANDEPOCHLEN 64
void dateandtimezone(char *buffer);
// Same, but for time defined by epoch tval
void dateandtimezoneepoch(char *buffer, time_t tval);
// like printf() except that we can control it better. Note --
// although the prototype is given here in utility.h, the function
// itself is defined differently in smartctl and smartd. So the
// function definition(s) are in smartd.c and in smartctl.c.
void pout(const char *fmt, ...)
__attribute_format_printf(1, 2);
// replacement for perror() with redirected output.
void syserror(const char *message);
// Function for processing -t selective... option in smartctl
int split_selective_arg(char *s, uint64_t *start, uint64_t *stop, int *mode);
// Replacement for exit(status)
// (exit is not compatible with C++ destructors)
#define EXIT(status) { throw (int)(status); }
// Compile time check of byte ordering
// (inline const function allows compiler to remove dead code)
inline bool isbigendian()
{
#ifdef WORDS_BIGENDIAN
return true;
#else
return false;
#endif
}
// Runtime check of ./configure result, throws on error.
void check_config();
// This value follows the peripheral device type value as defined in
// SCSI Primary Commands, ANSI INCITS 301:1997. It is also used in
// the ATA standard for packet devices to define the device type.
const char *packetdevicetype(int type);
// returns true if any of the n bytes are nonzero, else zero.
bool nonempty(const void * data, int size);
// needed to fix glibc bug
void FixGlibcTimeZoneBug();
// Copy not null terminated char array to null terminated string.
// Replace non-ascii characters. Remove leading and trailing blanks.
const char * format_char_array(char * str, int strsize, const char * chr, int chrsize);
// Version for fixed size buffers.
template<size_t STRSIZE, size_t CHRSIZE>
inline const char * format_char_array(char (& str)[STRSIZE], const char (& chr)[CHRSIZE])
{ return format_char_array(str, (int)STRSIZE, chr, (int)CHRSIZE); }
// Format integer with thousands separator
const char * format_with_thousands_sep(char * str, int strsize, uint64_t val,
const char * thousands_sep = 0);
// Format capacity with SI prefixes
const char * format_capacity(char * str, int strsize, uint64_t val,
const char * decimal_point = 0);
// Wrapper class for a raw data buffer
class raw_buffer
{
public:
explicit raw_buffer(unsigned sz, unsigned char val = 0)
: m_data(new unsigned char[sz]),
m_size(sz)
{ memset(m_data, val, m_size); }
~raw_buffer()
{ delete [] m_data; }
unsigned size() const
{ return m_size; }
unsigned char * data()
{ return m_data; }
const unsigned char * data() const
{ return m_data; }
private:
unsigned char * m_data;
unsigned m_size;
raw_buffer(const raw_buffer &);
void operator=(const raw_buffer &);
};
/// Wrapper class for FILE *.
class stdio_file
{
public:
explicit stdio_file(FILE * f = 0, bool owner = false)
: m_file(f), m_owner(owner) { }
stdio_file(const char * name, const char * mode)
: m_file(fopen(name, mode)), m_owner(true) { }
~stdio_file()
{
if (m_file && m_owner)
fclose(m_file);
}
bool open(const char * name, const char * mode)
{
if (m_file && m_owner)
fclose(m_file);
m_file = fopen(name, mode);
m_owner = true;
return !!m_file;
}
void open(FILE * f, bool owner = false)
{
if (m_file && m_owner)
fclose(m_file);
m_file = f;
m_owner = owner;
}
bool close()
{
if (!m_file)
return true;
bool ok = !ferror(m_file);
if (fclose(m_file))
ok = false;
m_file = 0;
return ok;
}
operator FILE * ()
{ return m_file; }
bool operator!() const
{ return !m_file; }
private:
FILE * m_file;
bool m_owner;
stdio_file(const stdio_file &);
void operator=(const stdio_file &);
};
/// Wrapper class for regex(3).
/// Supports copy & assignment and is compatible with STL containers.
class regular_expression
{
public:
// Construction & assignment
regular_expression();
regular_expression(const char * pattern, int flags,
bool throw_on_error = true);
~regular_expression();
regular_expression(const regular_expression & x);
regular_expression & operator=(const regular_expression & x);
/// Set and compile new pattern, return false on error.
bool compile(const char * pattern, int flags);
// Get pattern from last compile().
const char * get_pattern() const
{ return m_pattern.c_str(); }
/// Get error message from last compile().
const char * get_errmsg() const
{ return m_errmsg.c_str(); }
// Return true if pattern is not set or bad.
bool empty() const
{ return (m_pattern.empty() || !m_errmsg.empty()); }
/// Return true if substring matches pattern
bool match(const char * str, int flags = 0) const
{ return !regexec(&m_regex_buf, str, 0, (regmatch_t*)0, flags); }
/// Return true if full string matches pattern
bool full_match(const char * str, int flags = 0) const
{
regmatch_t range;
return ( !regexec(&m_regex_buf, str, 1, &range, flags)
&& range.rm_so == 0 && range.rm_eo == (int)strlen(str));
}
/// Return true if substring matches pattern, fill regmatch_t array.
bool execute(const char * str, unsigned nmatch, regmatch_t * pmatch, int flags = 0) const
{ return !regexec(&m_regex_buf, str, nmatch, pmatch, flags); }
private:
std::string m_pattern;
int m_flags;
regex_t m_regex_buf;
std::string m_errmsg;
void free_buf();
void copy(const regular_expression & x);
bool compile();
};
#ifdef _WIN32
// Get exe directory
//(implemented in os_win32.cpp)
std::string get_exe_dir();
#endif
#ifdef OLD_INTERFACE
// remaining controller types in old interface modules
#define CONTROLLER_UNKNOWN 0x00
#define CONTROLLER_ATA 0x01
#define CONTROLLER_SCSI 0x02
#endif
#endif
|