18#define __STDC_FORMAT_MACROS 1
38#include "svnversion.h"
45#ifndef USE_CLOCK_MONOTONIC
50#define USE_CLOCK_MONOTONIC 1
54#define USE_CLOCK_MONOTONIC 0
62 "Direct-access (disk)",
63 "Sequential-access (tape)",
66 "Write-once (optical disk)",
69 "Optical memory (optical disk)",
72 "Graphic arts pre-press (10)",
73 "Graphic arts pre-press (11)",
76 "Reduced block command (simplified disk)",
77 "Optical card reader/writer"
82#define BUILD_INFO "(local build)"
90#ifndef SMARTMONTOOLS_RELEASE_DATE
94#ifdef SMARTMONTOOLS_SVN_REV
95 SMARTMONTOOLS_SVN_DATE
" r" SMARTMONTOOLS_SVN_REV
97 "(build date " __DATE__
")"
100 "Copyright (C) 2002-23, Bruce Allen, Christian Franke, www.smartmontools.org\n",
101 prog_name,
smi()->get_os_version_str().c_str()
108 info +=
" comes with ABSOLUTELY NO WARRANTY. This is free\n"
109 "software, and you are welcome to redistribute it under\n"
110 "the terms of the GNU General Public License; either\n"
111 "version 2, or (at your option) any later version.\n"
112 "See https://www.gnu.org for further details.\n"
114#ifndef SMARTMONTOOLS_RELEASE_DATE
115 "smartmontools pre-release " PACKAGE_VERSION
"\n"
117 "smartmontools release " PACKAGE_VERSION
118 " dated " SMARTMONTOOLS_RELEASE_DATE
" at " SMARTMONTOOLS_RELEASE_TIME
"\n"
120#ifdef SMARTMONTOOLS_SVN_REV
121 "smartmontools SVN rev " SMARTMONTOOLS_SVN_REV
122 " dated " SMARTMONTOOLS_SVN_DATE
" at " SMARTMONTOOLS_SVN_TIME
"\n"
124 "smartmontools SVN rev is unknown\n"
126 "smartmontools build host: " SMARTMONTOOLS_BUILD_HOST
"\n"
127 "smartmontools build with: "
130#define N2S(s) N2S_(s)
131#if __cplusplus == 202002
133#elif __cplusplus == 201703
135#elif __cplusplus == 201402
137#elif __cplusplus == 201103
140 "C++(" N2S(__cplusplus)
")"
145#if defined(__GNUC__) && defined(__VERSION__)
148#ifdef __MINGW64_VERSION_STR
149 ", MinGW-w64 " __MINGW64_VERSION_STR
152 "smartmontools configure arguments:"
153#ifdef SOURCE_DATE_EPOCH
154 " [hidden in reproducible builds]\n"
155 "reproducible build SOURCE_DATE_EPOCH: "
158#ifdef SOURCE_DATE_EPOCH
159 char ts[32];
struct tm tmbuf;
160 strftime(ts,
sizeof(ts),
"%Y-%m-%d %H:%M:%S",
time_to_tm_local(&tmbuf, SOURCE_DATE_EPOCH));
161 info +=
strprintf(
"%u (%s)", (
unsigned)SOURCE_DATE_EPOCH, ts);
163 info += (
sizeof(SMARTMONTOOLS_CONFIGURE_ARGS) > 1 ?
164 SMARTMONTOOLS_CONFIGURE_ARGS :
" [no arguments given]");
173#if defined (__SVR4) && defined (__sun)
174static const char *TIMEZONE_FILE =
"/etc/TIMEZONE";
176static char *ReadSiteDefaultTimezone(){
182 fp = fopen(TIMEZONE_FILE,
"r");
183 if(fp == NULL)
return NULL;
184 while(fgets(buf,
sizeof(buf), fp)) {
185 if (strncmp(buf,
"TZ=", 3))
188 if (buf[n] ==
'\n') buf[n] = 0;
210 putenv((
char *)
"TZ=GMT");
212 putenv((
char *)
"TZ");
222#elif defined (__SVR4) && defined (__sun)
229 enum tzstate { NOT_CALLED_YET, USER_TIMEZONE, TRACK_TIMEZONE };
230 static enum tzstate state = NOT_CALLED_YET;
232 static struct stat prev_stat;
233 static char *prev_tz;
234 struct stat curr_stat;
237 if(state == NOT_CALLED_YET) {
239 state = USER_TIMEZONE;
241 state = TRACK_TIMEZONE;
242 if(stat(TIMEZONE_FILE, &prev_stat)) {
243 state = USER_TIMEZONE;
245 prev_tz = ReadSiteDefaultTimezone();
246 if(prev_tz) putenv(prev_tz);
250 }
else if(state == TRACK_TIMEZONE) {
251 if(stat(TIMEZONE_FILE, &curr_stat) == 0
252 && (curr_stat.st_ctime != prev_stat.st_ctime
253 || curr_stat.st_mtime != prev_stat.st_mtime)) {
255 curr_tz = ReadSiteDefaultTimezone();
258 if(prev_tz) free(prev_tz);
259 prev_tz = curr_tz; prev_stat = curr_stat;
274static char * fixtzname(
char * dest,
int destsize,
const char * src)
277 while (src[i] && j < destsize-1) {
278 int i2 = (
const char *)_mbsinc((
const unsigned char *)src+i) - src;
282 if (
'A' <= src[i] && src[i] <=
'Z')
312 if (!localtime_r(&t, tp))
313 throw std::runtime_error(
"localtime_r() failed");
316 if (localtime_s(tp, &t))
317 throw std::runtime_error(
"localtime_s() failed");
340 if (!asctime_r(tmval, datebuffer))
341 throw std::runtime_error(
"asctime_r() failed");
344 if (asctime_s(datebuffer,
sizeof(datebuffer), tmval))
345 throw std::runtime_error(
"asctime_s() failed");
349 int lenm1 = strlen(datebuffer) - 1;
350 datebuffer[lenm1>=0?lenm1:0]=
'\0';
352#if defined(_WIN32) && defined(_MSC_VER)
354 #define tzname _tzname
358 const char * timezonename;
359 if (tmval->tm_isdst==0)
361 timezonename=tzname[0];
362 else if (tmval->tm_isdst>0)
364 timezonename=tzname[1];
372 char tzfixbuf[6+1] =
"";
374 timezonename=fixtzname(tzfixbuf,
sizeof(tzfixbuf), timezonename);
389 const char *errormessage=strerror(errno);
393 if (message && *message)
394 pout(
"%s: %s\n",message, errormessage);
396 pout(
"%s\n",errormessage);
398 else if (message && *message)
399 pout(
"%s\n",message);
424 for (
int i = 0; (c = pattern[i]); i++) {
434 if (pattern[++i] ==
'^')
438 while ((c = pattern[i]) && c !=
']')
448 else if (c ==
')' && --level < 0)
449 return "Unmatched ')'";
453 if ( (c ==
'|' && ( i == 0 || !(c1 = pattern[i+1])
454 || c1 ==
'|' || c1 ==
')' || c1 ==
'$'))
455 || ((c ==
'(' || c ==
'^') && pattern[i+1] ==
'|') )
456 return "Empty '|' subexpression";
459 return (
const char *)0;
464#ifndef WITH_CXX11_REGEX
477: m_pattern(x.m_pattern),
507 "Unable to recompile regular expression \"%s\": %s",
519 "error in regular expression \"%s\": %s",
525#ifndef WITH_CXX11_REGEX
534#ifdef WITH_CXX11_REGEX
536 m_regex.assign(
m_pattern, std::regex_constants::extended);
538 catch (std::regex_error & ex) {
547 regerror(errcode, &
m_regex_buf, errmsg,
sizeof(errmsg));
557#ifdef WITH_CXX11_REGEX
558 m_regex = std::regex();
571#ifdef WITH_CXX11_REGEX
572 return std::regex_match(str, m_regex);
576 && range.rm_so == 0 && range.rm_eo == (
int)strlen(str));
582#ifdef WITH_CXX11_REGEX
584 if (!std::regex_search(str, m, m_regex))
586 unsigned sz = m.size();
587 for (
unsigned i = 0; i < nmatch; i++) {
588 if (i < sz && *m[i].first) {
589 pmatch[i].rm_so = m[i].first - str;
590 pmatch[i].rm_eo = m[i].second - str;
593 pmatch[i].rm_so = pmatch[i].rm_eo = -1;
598 return !regexec(&
m_regex_buf, str, nmatch, pmatch, 0);
607 uint64_t *stop,
int *mode)
610 if (!(
s = strchr(
s,
',')))
613 if (!isdigit((
int)(*++
s))) {
615 if (!strncmp(
s,
"redo", 4))
617 else if (!strncmp(
s,
"next", 4))
619 else if (!strncmp(
s,
"cont", 4))
634 *start = strtoull(
s, &tailptr, 0);
637 if (!(!errno && (add || *
s ==
'-')))
639 if (!strcmp(
s,
"-max")) {
640 *stop = ~(uint64_t)0;
646 *stop = strtoull(
s+1, &tailptr, 0);
647 if (errno || *tailptr !=
'\0')
660 for (
int i = 0; i <
size; i++)
661 if (((
const unsigned char *)
data)[i])
671 while (
b < chrsize && chr[
b] ==
' ')
674 while (
b+n < chrsize && chr[
b+n])
676 while (n > 0 && chr[
b+n-1] ==
' ')
682 for (
int i = 0; i < n; i++) {
684 str[i] = (
' ' <= c && c <=
'~' ? c :
'?');
693 const char * thousands_sep )
695 if (!thousands_sep) {
698 setlocale(LC_ALL,
"");
699 const struct lconv * currentlocale = localeconv();
700 if (*(currentlocale->thousands_sep))
701 thousands_sep = currentlocale->thousands_sep;
706 snprintf(num,
sizeof(num),
"%" PRIu64, val);
707 int numlen = strlen(num);
712 while (i < numlen && (numlen - i) % 3 != 0 && j < strsize-1);
715 while (i < numlen && j < strsize-1) {
716 j += snprintf(str+j, strsize-j,
"%s%.3s", thousands_sep, num+i);
725 const char * decimal_point )
727 if (!decimal_point) {
730 setlocale(LC_ALL,
"");
731 const struct lconv * currentlocale = localeconv();
732 if (*(currentlocale->decimal_point))
733 decimal_point = currentlocale->decimal_point;
737 const unsigned factor = 1000;
738 static const char prefixes[] =
" KMGTP";
743 for (uint64_t d2 = d * factor; val >= d2; d2 *= factor) {
745 if (++i >=
sizeof(prefixes)-2)
750 uint64_t n = val / d;
752 snprintf(str, strsize,
"%u B", (
unsigned)n);
754 snprintf(str, strsize,
"%" PRIu64
" %cB", n, prefixes[i]);
756 snprintf(str, strsize,
"%" PRIu64
"%s%u %cB", n, decimal_point,
757 (
unsigned)(((val % d) * 10) / d), prefixes[i]);
759 snprintf(str, strsize,
"%" PRIu64
"%s%02u %cB", n, decimal_point,
760 (
unsigned)(((val % d) * 100) / d), prefixes[i]);
771 buf[
sizeof(buf)-1] = 0;
783#if defined(HAVE___INT128)
787static int snprint_uint128(
char * str,
int strsize,
unsigned __int128 value)
792 if (value <= 0xffffffffffffffffULL) {
794 return snprintf(str, (
size_t)strsize,
"%" PRIu64, (uint64_t)value);
798 const uint64_t e19 = 10000000000000000000ULL;
799 int len1 = snprint_uint128(str, strsize, value / e19);
804 int len2 = snprintf(str + (len1 < strsize ? len1 : strsize - 1),
805 (
size_t)(len1 < strsize ? strsize - len1 : 1),
806 "%019" PRIu64, (uint64_t)(value % e19) );
814const char *
uint128_hilo_to_str(
char * str,
int strsize, uint64_t value_hi, uint64_t value_lo)
816 snprint_uint128(str, strsize, ((
unsigned __int128)value_hi << 64) | value_lo);
820#elif defined(HAVE_LONG_DOUBLE_WIDER_PRINTF)
823const char *
uint128_hilo_to_str(
char * str,
int strsize, uint64_t value_hi, uint64_t value_lo)
825 snprintf(str, strsize,
"%.0Lf", value_hi * (0xffffffffffffffffULL + 1.0L) + value_lo);
834 snprintf(str, strsize,
"%.0f", value_hi * (0xffffffffffffffffULL + 1.0) + value_lo);
843#if USE_CLOCK_MONOTONIC
845 if (clock_gettime(CLOCK_MONOTONIC, &ts))
847 return ts.tv_sec * 1000000LL + ts.tv_nsec / 1000;
849 return std::chrono::duration_cast<std::chrono::microseconds>(
850 std::chrono::high_resolution_clock::now().time_since_epoch()
860 unsigned char c[
sizeof(int) == 4 ? 8 : -1];
862 } x = {{1, 2, 3, 4, 5, 6, 7, 8}};
863 const uint64_t le = 0x0807060504030201ULL;
864 const uint64_t be = 0x0102030405060708ULL;
873 throw std::logic_error(
"CPU endianness does not match compile time test");
876#if defined(__GNUC__) && (__GNUC__ >= 7)
885 char buf[] =
"ABCDEFGHI";
886 int n1 = snprintf(buf, 8,
"123456789");
887 int n2 = snprintf(buf, 0,
"X");
888 if (!(!strcmp(buf,
"1234567") && n1 == 9 && n2 == 1))
889 throw std::logic_error(
"Function snprintf() does not conform to C99");
Wrapper class for POSIX regex(3) or std::regex Supports copy & assignment and is compatible with STL ...
bool full_match(const char *str) const
Return true if full string matches pattern.
regular_expression & operator=(const regular_expression &x)
void copy_buf(const regular_expression &x)
bool execute(const char *str, unsigned nmatch, match_range *pmatch) const
Return true if substring matches pattern, fill match_range array.
smart_interface * smi()
Global access to the (usually singleton) smart_interface.
static uint64_t sg_get_unaligned_le64(const void *p)
static uint32_t sg_get_unaligned_le32(const void *p)
static uint64_t sg_get_unaligned_be64(const void *p)
static uint16_t sg_get_unaligned_be16(const void *p)
static uint16_t sg_get_unaligned_le16(const void *p)
static uint32_t sg_get_unaligned_be32(const void *p)
const char const char * fmt
const char const char va_list ap
vsnprintf(buf, sizeof(buf), fmt, ap)
void pout(const char *fmt,...)
void FixGlibcTimeZoneBug()
const char * format_char_array(char *str, int strsize, const char *chr, int chrsize)
void dateandtimezoneepoch(char(&buffer)[DATEANDEPOCHLEN], time_t tval)
long long get_timer_usec()
Get microseconds since some unspecified starting point.
const char * packet_types[]
const char * format_capacity(char *str, int strsize, uint64_t val, const char *decimal_point)
const char * format_with_thousands_sep(char *str, int strsize, uint64_t val, const char *thousands_sep)
void syserror(const char *message)
std::string strprintf(const char *fmt,...)
const char * utility_cpp_cvsid
static const char * check_regex(const char *pattern)
bool nonempty(const void *data, int size)
static void check_endianness()
int split_selective_arg(char *s, uint64_t *start, uint64_t *stop, int *mode)
const char * uint128_hilo_to_str(char *str, int strsize, uint64_t value_hi, uint64_t value_lo)
const char * packetdevicetype(int type)
struct tm * time_to_tm_local(struct tm *tp, time_t t)
static void check_snprintf()
std::string format_version_info(const char *prog_name, bool full)
std::string std::string vstrprintf(const char *fmt, va_list ap)
std::string strprintf(const char *fmt,...) __attribute_format_printf(1
bool nonempty(const void *data, int size)
#define __attribute_format_printf(x, y)