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)"
91#ifndef SMARTMONTOOLS_RELEASE_DATE
95#ifdef SMARTMONTOOLS_SVN_REV
96 SMARTMONTOOLS_SVN_DATE
" r" SMARTMONTOOLS_SVN_REV
98 "(build date " __DATE__
")"
101 prog_name,
smi()->get_os_version_str().c_str()
106 info +=
"Copyright (C) 2002-24, Bruce Allen, Christian Franke, www.smartmontools.org\n";
112 info +=
" comes with ABSOLUTELY NO WARRANTY. This is free\n"
113 "software, and you are welcome to redistribute it under\n"
114 "the terms of the GNU General Public License; either\n"
115 "version 2, or (at your option) any later version.\n"
116 "See https://www.gnu.org for further details.\n"
118#ifndef SMARTMONTOOLS_RELEASE_DATE
119 "smartmontools pre-release " PACKAGE_VERSION
"\n"
121 "smartmontools release " PACKAGE_VERSION
122 " dated " SMARTMONTOOLS_RELEASE_DATE
" at " SMARTMONTOOLS_RELEASE_TIME
"\n"
124#ifdef SMARTMONTOOLS_SVN_REV
125 "smartmontools SVN rev " SMARTMONTOOLS_SVN_REV
126#ifdef SMARTMONTOOLS_GIT_HASH
127 " (git " SMARTMONTOOLS_GIT_HASH
")"
129 " dated " SMARTMONTOOLS_SVN_DATE
" at " SMARTMONTOOLS_SVN_TIME
"\n"
131 "smartmontools SVN rev is unknown\n"
133 "smartmontools build host: " SMARTMONTOOLS_BUILD_HOST
"\n"
134 "smartmontools build with: "
137#define N2S(s) N2S_(s)
138#if __cplusplus == 202002
140#elif __cplusplus == 201703
142#elif __cplusplus == 201402
144#elif __cplusplus == 201103
147 "C++(" N2S(__cplusplus)
")"
152#if defined(__GNUC__) && defined(__VERSION__)
155#ifdef __MINGW64_VERSION_STR
156 ", MinGW-w64 " __MINGW64_VERSION_STR
159 "smartmontools configure arguments:"
160#ifdef SOURCE_DATE_EPOCH
161 " [hidden in reproducible builds]\n"
162 "reproducible build SOURCE_DATE_EPOCH: "
165#ifdef SOURCE_DATE_EPOCH
166 char ts[32];
struct tm tmbuf;
167 strftime(ts,
sizeof(ts),
"%Y-%m-%d %H:%M:%S",
time_to_tm_local(&tmbuf, SOURCE_DATE_EPOCH));
168 info +=
strprintf(
"%u (%s)", (
unsigned)SOURCE_DATE_EPOCH, ts);
170 info += (
sizeof(SMARTMONTOOLS_CONFIGURE_ARGS) > 1 ?
171 SMARTMONTOOLS_CONFIGURE_ARGS :
" [no arguments given]");
180#if defined (__SVR4) && defined (__sun)
181static const char *TIMEZONE_FILE =
"/etc/TIMEZONE";
183static char *ReadSiteDefaultTimezone(){
189 fp = fopen(TIMEZONE_FILE,
"r");
190 if(fp == NULL)
return NULL;
191 while(fgets(buf,
sizeof(buf), fp)) {
192 if (strncmp(buf,
"TZ=", 3))
195 if (buf[n] ==
'\n') buf[n] = 0;
217 putenv((
char *)
"TZ=GMT");
219 putenv((
char *)
"TZ");
223 const char * tz = getenv(
"TZ");
240#elif defined (__SVR4) && defined (__sun)
247 enum tzstate { NOT_CALLED_YET, USER_TIMEZONE, TRACK_TIMEZONE };
248 static enum tzstate state = NOT_CALLED_YET;
250 static struct stat prev_stat;
251 static char *prev_tz;
252 struct stat curr_stat;
255 if(state == NOT_CALLED_YET) {
257 state = USER_TIMEZONE;
259 state = TRACK_TIMEZONE;
260 if(stat(TIMEZONE_FILE, &prev_stat)) {
261 state = USER_TIMEZONE;
263 prev_tz = ReadSiteDefaultTimezone();
264 if(prev_tz) putenv(prev_tz);
268 }
else if(state == TRACK_TIMEZONE) {
269 if(stat(TIMEZONE_FILE, &curr_stat) == 0
270 && (curr_stat.st_ctime != prev_stat.st_ctime
271 || curr_stat.st_mtime != prev_stat.st_mtime)) {
273 curr_tz = ReadSiteDefaultTimezone();
276 if(prev_tz) free(prev_tz);
277 prev_tz = curr_tz; prev_stat = curr_stat;
292static char * fixtzname(
char * dest,
int destsize,
const char * src)
295 while (src[i] && j < destsize-1) {
296 int i2 = (
const char *)_mbsinc((
const unsigned char *)src+i) - src;
300 if (
'A' <= src[i] && src[i] <=
'Z')
330 if (!localtime_r(&t, tp))
331 throw std::runtime_error(
"localtime_r() failed");
335 if (!localtime_s(&t, tp))
336 throw std::runtime_error(
"localtime_s() failed");
340 if (_localtime64_s(tp, &t64))
341 throw std::runtime_error(
"_localtime64_s() failed");
364 if (!asctime_r(tmval, datebuffer))
365 throw std::runtime_error(
"asctime_r() failed");
368 if (asctime_s(datebuffer,
sizeof(datebuffer), tmval))
369 throw std::runtime_error(
"asctime_s() failed");
373 int lenm1 = strlen(datebuffer) - 1;
374 datebuffer[lenm1>=0?lenm1:0]=
'\0';
376#if defined(_WIN32) && defined(_MSC_VER)
378 #define tzname _tzname
382 const char * timezonename;
383 if (tmval->tm_isdst==0)
385 timezonename=tzname[0];
386 else if (tmval->tm_isdst>0)
388 timezonename=tzname[1];
396 char tzfixbuf[6+1] =
"";
398 timezonename=fixtzname(tzfixbuf,
sizeof(tzfixbuf), timezonename);
413 const char *errormessage=strerror(errno);
417 if (message && *message)
418 pout(
"%s: %s\n",message, errormessage);
420 pout(
"%s\n",errormessage);
422 else if (message && *message)
423 pout(
"%s\n",message);
448 for (
int i = 0; (c = pattern[i]); i++) {
458 if (pattern[++i] ==
'^')
462 while ((c = pattern[i]) && c !=
']')
472 else if (c ==
')' && --level < 0)
473 return "Unmatched ')'";
477 if ( (c ==
'|' && ( i == 0 || !(c1 = pattern[i+1])
478 || c1 ==
'|' || c1 ==
')' || c1 ==
'$'))
479 || ((c ==
'(' || c ==
'^') && pattern[i+1] ==
'|') )
480 return "Empty '|' subexpression";
483 return (
const char *)0;
488#ifndef WITH_CXX11_REGEX
501: m_pattern(x.m_pattern),
531 "Unable to recompile regular expression \"%s\": %s",
543 "error in regular expression \"%s\": %s",
549#ifndef WITH_CXX11_REGEX
558#ifdef WITH_CXX11_REGEX
560 m_regex.assign(
m_pattern, std::regex_constants::extended);
562 catch (std::regex_error & ex) {
571 regerror(errcode, &
m_regex_buf, errmsg,
sizeof(errmsg));
581#ifdef WITH_CXX11_REGEX
582 m_regex = std::regex();
595#ifdef WITH_CXX11_REGEX
596 return std::regex_match(str, m_regex);
600 && range.rm_so == 0 && range.rm_eo == (
int)strlen(str));
606#ifdef WITH_CXX11_REGEX
608 if (!std::regex_search(str, m, m_regex))
610 unsigned sz = m.size();
611 for (
unsigned i = 0; i < nmatch; i++) {
612 if (i < sz && *m[i].first) {
613 pmatch[i].rm_so = m[i].first - str;
614 pmatch[i].rm_eo = m[i].second - str;
617 pmatch[i].rm_so = pmatch[i].rm_eo = -1;
622 return !regexec(&
m_regex_buf, str, nmatch, pmatch, 0);
631 uint64_t *stop,
int *mode)
634 if (!(
s = strchr(
s,
',')))
637 if (!isdigit((
int)(*++
s))) {
639 if (!strncmp(
s,
"redo", 4))
641 else if (!strncmp(
s,
"next", 4))
643 else if (!strncmp(
s,
"cont", 4))
658 *start = strtoull(
s, &tailptr, 0);
661 if (!(!errno && (add || *
s ==
'-')))
663 if (!strcmp(
s,
"-max")) {
664 *stop = ~(uint64_t)0;
670 *stop = strtoull(
s+1, &tailptr, 0);
671 if (errno || *tailptr !=
'\0')
684 for (
int i = 0; i <
size; i++)
685 if (((
const unsigned char *)
data)[i])
695 while (
b < chrsize && chr[
b] ==
' ')
698 while (
b+n < chrsize && chr[
b+n])
700 while (n > 0 && chr[
b+n-1] ==
' ')
706 for (
int i = 0; i < n; i++) {
708 str[i] = (
' ' <= c && c <=
'~' ? c :
'?');
717 const char * thousands_sep )
719 if (!thousands_sep) {
722 setlocale(LC_ALL,
"");
723 const struct lconv * currentlocale = localeconv();
724 if (*(currentlocale->thousands_sep))
725 thousands_sep = currentlocale->thousands_sep;
730 snprintf(num,
sizeof(num),
"%" PRIu64, val);
731 int numlen = strlen(num);
736 while (i < numlen && (numlen - i) % 3 != 0 && j < strsize-1);
739 while (i < numlen && j < strsize-1) {
740 j += snprintf(str+j, strsize-j,
"%s%.3s", thousands_sep, num+i);
749 const char * decimal_point )
751 if (!decimal_point) {
754 setlocale(LC_ALL,
"");
755 const struct lconv * currentlocale = localeconv();
756 if (*(currentlocale->decimal_point))
757 decimal_point = currentlocale->decimal_point;
761 const unsigned factor = 1000;
762 static const char prefixes[] =
" KMGTP";
767 for (uint64_t d2 = d * factor; val >= d2; d2 *= factor) {
769 if (++i >=
sizeof(prefixes)-2)
774 uint64_t n = val / d;
776 snprintf(str, strsize,
"%u B", (
unsigned)n);
778 snprintf(str, strsize,
"%" PRIu64
" %cB", n, prefixes[i]);
780 snprintf(str, strsize,
"%" PRIu64
"%s%u %cB", n, decimal_point,
781 (
unsigned)(((val % d) * 10) / d), prefixes[i]);
783 snprintf(str, strsize,
"%" PRIu64
"%s%02u %cB", n, decimal_point,
784 (
unsigned)(((val % d) * 100) / d), prefixes[i]);
795 buf[
sizeof(buf)-1] = 0;
807#if defined(HAVE___INT128)
811static int snprint_uint128(
char * str,
int strsize,
unsigned __int128 value)
816 if (value <= 0xffffffffffffffffULL) {
818 return snprintf(str, (
size_t)strsize,
"%" PRIu64, (uint64_t)value);
822 const uint64_t e19 = 10000000000000000000ULL;
823 int len1 = snprint_uint128(str, strsize, value / e19);
828 int len2 = snprintf(str + (len1 < strsize ? len1 : strsize - 1),
829 (
size_t)(len1 < strsize ? strsize - len1 : 1),
830 "%019" PRIu64, (uint64_t)(value % e19) );
838const char *
uint128_hilo_to_str(
char * str,
int strsize, uint64_t value_hi, uint64_t value_lo)
840 snprint_uint128(str, strsize, ((
unsigned __int128)value_hi << 64) | value_lo);
844#elif defined(HAVE_LONG_DOUBLE_WIDER_PRINTF)
847const char *
uint128_hilo_to_str(
char * str,
int strsize, uint64_t value_hi, uint64_t value_lo)
849 snprintf(str, strsize,
"%.0Lf", value_hi * (0xffffffffffffffffULL + 1.0L) + value_lo);
858 snprintf(str, strsize,
"%.0f", value_hi * (0xffffffffffffffffULL + 1.0) + value_lo);
867#if USE_CLOCK_MONOTONIC
869 if (clock_gettime(CLOCK_MONOTONIC, &ts))
871 return ts.tv_sec * 1000000LL + ts.tv_nsec / 1000;
873 return std::chrono::duration_cast<std::chrono::microseconds>(
874 std::chrono::high_resolution_clock::now().time_since_epoch()
884 unsigned char c[
sizeof(int) == 4 ? 8 : -1];
886 } x = {{1, 2, 3, 4, 5, 6, 7, 8}};
887 const uint64_t le = 0x0807060504030201ULL;
888 const uint64_t be = 0x0102030405060708ULL;
897 throw std::logic_error(
"CPU endianness does not match compile time test");
900#if defined(__GNUC__) && (__GNUC__ >= 7)
909 char buf[] =
"ABCDEFGHI";
910 int n1 = snprintf(buf, 8,
"123456789");
911 int n2 = snprintf(buf, 0,
"X");
912 if (!(!strcmp(buf,
"1234567") && n1 == 9 && n2 == 1))
913 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)
std::string format_version_info(const char *prog_name, int lines)
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 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)