4 * Home page of code is: http://www.smartmontools.org
6 * Copyright (C) 2002-12 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
13 // THIS FILE IS INTENDED FOR UTILITY ROUTINES THAT ARE APPLICABLE TO
14 // BOTH SCSI AND ATA DEVICES, AND THAT MAY BE USED IN SMARTD,
18 #define __STDC_FORMAT_MACROS 1 // enable PRI* for C++
33 #include <mbstring.h> // _mbsinc()
38 #include "svnversion.h"
42 #include "dev_interface.h"
43 #include "sg_unaligned.h"
45 const char * utility_cpp_cvsid
= "$Id: utility.cpp 4842 2018-12-02 16:07:26Z chrfranke $"
48 const char * packet_types
[] = {
49 "Direct-access (disk)",
50 "Sequential-access (tape)",
53 "Write-once (optical disk)",
56 "Optical memory (optical disk)",
59 "Graphic arts pre-press (10)",
60 "Graphic arts pre-press (11)",
63 "Reduced block command (simplified disk)",
64 "Optical card reader/writer"
67 // BUILD_INFO can be provided by package maintainers
69 #define BUILD_INFO "(local build)"
72 // Make version information string
73 std::string
format_version_info(const char * prog_name
, bool full
/*= false*/)
75 std::string info
= strprintf(
76 "%s " PACKAGE_VERSION
" "
77 #ifdef SMARTMONTOOLS_SVN_REV
78 SMARTMONTOOLS_SVN_DATE
" r" SMARTMONTOOLS_SVN_REV
80 "(build date " __DATE__
")" // checkout without expansion of Id keywords
82 " [%s] " BUILD_INFO
"\n"
83 "Copyright (C) 2002-18, Bruce Allen, Christian Franke, www.smartmontools.org\n",
84 prog_name
, smi()->get_os_version_str().c_str()
91 info
+= " comes with ABSOLUTELY NO WARRANTY. This is free\n"
92 "software, and you are welcome to redistribute it under\n"
93 "the terms of the GNU General Public License; either\n"
94 "version 2, or (at your option) any later version.\n"
95 "See http://www.gnu.org for further details.\n"
97 "smartmontools release " PACKAGE_VERSION
98 " dated " SMARTMONTOOLS_RELEASE_DATE
" at " SMARTMONTOOLS_RELEASE_TIME
"\n"
99 #ifdef SMARTMONTOOLS_SVN_REV
100 "smartmontools SVN rev " SMARTMONTOOLS_SVN_REV
101 " dated " SMARTMONTOOLS_SVN_DATE
" at " SMARTMONTOOLS_SVN_TIME
"\n"
103 "smartmontools SVN rev is unknown\n"
105 "smartmontools build host: " SMARTMONTOOLS_BUILD_HOST
"\n"
106 "smartmontools build with: "
109 #define N2S(s) "(" N2S_(s) ")"
110 #if __cplusplus > 201703
111 "C++2x" N2S(__cplusplus
)
112 #elif __cplusplus == 201703
114 #elif __cplusplus > 201402
115 "C++14" N2S(__cplusplus
)
116 #elif __cplusplus == 201402
118 #elif __cplusplus > 201103
119 "C++11" N2S(__cplusplus
)
120 #elif __cplusplus == 201103
122 #elif __cplusplus > 199711
123 "C++98" N2S(__cplusplus
)
124 #elif __cplusplus == 199711
127 "C++" N2S(__cplusplus
)
132 #if defined(__GNUC__) && defined(__VERSION__) // works also with CLang
136 "smartmontools configure arguments:"
138 info
+= (sizeof(SMARTMONTOOLS_CONFIGURE_ARGS
) > 1 ?
139 SMARTMONTOOLS_CONFIGURE_ARGS
: " [no arguments given]");
145 // Solaris only: Get site-default timezone. This is called from
146 // UpdateTimezone() when TZ environment variable is unset at startup.
147 #if defined (__SVR4) && defined (__sun)
148 static const char *TIMEZONE_FILE
= "/etc/TIMEZONE";
150 static char *ReadSiteDefaultTimezone(){
156 fp
= fopen(TIMEZONE_FILE
, "r");
157 if(fp
== NULL
) return NULL
;
158 while(fgets(buf
, sizeof(buf
), fp
)) {
159 if (strncmp(buf
, "TZ=", 3)) // searches last "TZ=" line
162 if (buf
[n
] == '\n') buf
[n
] = 0;
171 // Make sure that this executable is aware if the user has changed the
172 // time-zone since the last time we polled devices. The canonical
173 // example is a user who starts smartd on a laptop, then flies across
174 // time-zones with a laptop, and then changes the timezone, WITHOUT
175 // restarting smartd. This is a work-around for a bug in
176 // GLIBC. Yuk. See bug number 48184 at http://bugs.debian.org and
177 // thanks to Ian Redfern for posting a workaround.
179 // Please refer to the smartd manual page, in the section labeled LOG
180 // TIMESTAMP TIMEZONE.
181 void FixGlibcTimeZoneBug(){
184 putenv((char *)"TZ=GMT"); // POSIX prototype is 'int putenv(char *)'
186 putenv((char *)"TZ");
193 putenv("TZ="); // empty value removes TZ, putenv("TZ") does nothing
196 #elif defined (__SVR4) && defined (__sun)
197 // In Solaris, putenv("TZ=") sets null string and invalid timezone.
198 // putenv("TZ") does nothing. With invalid TZ, tzset() do as if
199 // TZ=GMT. With TZ unset, /etc/TIMEZONE will be read only _once_ at
200 // first tzset() call. Conclusion: Unlike glibc, dynamic
201 // configuration of timezone can be done only by changing actual
202 // value of TZ environment value.
203 enum tzstate
{ NOT_CALLED_YET
, USER_TIMEZONE
, TRACK_TIMEZONE
};
204 static enum tzstate state
= NOT_CALLED_YET
;
206 static struct stat prev_stat
;
207 static char *prev_tz
;
208 struct stat curr_stat
;
211 if(state
== NOT_CALLED_YET
) {
213 state
= USER_TIMEZONE
; // use supplied timezone
215 state
= TRACK_TIMEZONE
;
216 if(stat(TIMEZONE_FILE
, &prev_stat
)) {
217 state
= USER_TIMEZONE
; // no TZ, no timezone file; use GMT forever
219 prev_tz
= ReadSiteDefaultTimezone(); // track timezone file change
220 if(prev_tz
) putenv(prev_tz
);
224 } else if(state
== TRACK_TIMEZONE
) {
225 if(stat(TIMEZONE_FILE
, &curr_stat
) == 0
226 && (curr_stat
.st_ctime
!= prev_stat
.st_ctime
227 || curr_stat
.st_mtime
!= prev_stat
.st_mtime
)) {
228 // timezone file changed
229 curr_tz
= ReadSiteDefaultTimezone();
232 if(prev_tz
) free(prev_tz
);
233 prev_tz
= curr_tz
; prev_stat
= curr_stat
;
239 // OTHER OS/LIBRARY FIXES SHOULD GO HERE, IF DESIRED. PLEASE TRY TO
240 // KEEP THEM INDEPENDENT.
245 // Fix strings in tzname[] to avoid long names with non-ascii characters.
246 // If TZ is not set, tzset() in the MSVC runtime sets tzname[] to the
247 // national language timezone names returned by GetTimezoneInformation().
248 static char * fixtzname(char * dest
, int destsize
, const char * src
)
251 while (src
[i
] && j
< destsize
-1) {
252 int i2
= (const char *)_mbsinc((const unsigned char *)src
+i
) - src
;
254 i
= i2
; // Ignore multibyte chars
256 if ('A' <= src
[i
] && src
[i
] <= 'Z')
257 dest
[j
++] = src
[i
]; // "Pacific Standard Time" => "PST"
268 // This value follows the peripheral device type value as defined in
269 // SCSI Primary Commands, ANSI INCITS 301:1997. It is also used in
270 // the ATA standard for packet devices to define the device type.
271 const char *packetdevicetype(int type
){
273 return packet_types
[type
];
281 // Utility function prints date and time and timezone into a character
282 // buffer of length 64. All the fuss is needed to get the right
283 // timezone info (sigh).
284 void dateandtimezoneepoch(char (& buffer
)[DATEANDEPOCHLEN
], time_t tval
)
287 const char *timezonename
;
288 char datebuffer
[DATEANDEPOCHLEN
];
291 FixGlibcTimeZoneBug();
293 // Get the time structure. We need this to determine if we are in
294 // daylight savings time or not.
295 tmval
=localtime(&tval
);
297 // Convert to an ASCII string, put in datebuffer
298 // same as: asctime_r(tmval, datebuffer);
299 strncpy(datebuffer
, asctime(tmval
), DATEANDEPOCHLEN
);
300 datebuffer
[DATEANDEPOCHLEN
-1]='\0';
303 lenm1
=strlen(datebuffer
)-1;
304 datebuffer
[lenm1
>=0?lenm1
:0]='\0';
306 #if defined(_WIN32) && defined(_MSC_VER)
307 // tzname is missing in MSVC14
308 #define tzname _tzname
311 // correct timezone name
312 if (tmval
->tm_isdst
==0)
313 // standard time zone
314 timezonename
=tzname
[0];
315 else if (tmval
->tm_isdst
>0)
316 // daylight savings in effect
317 timezonename
=tzname
[1];
319 // unable to determine if daylight savings in effect
323 // Fix long non-ascii timezone names
324 // cppcheck-suppress variableScope
325 char tzfixbuf
[6+1] = "";
327 timezonename
=fixtzname(tzfixbuf
, sizeof(tzfixbuf
), timezonename
);
330 // Finally put the information into the buffer as needed.
331 snprintf(buffer
, DATEANDEPOCHLEN
, "%s %s", datebuffer
, timezonename
);
336 // A replacement for perror() that sends output to our choice of
337 // printing. If errno not set then just print message.
338 void syserror(const char *message
){
341 // Get the correct system error message:
342 const char *errormessage
=strerror(errno
);
344 // Check that caller has handed a sensible string, and provide
345 // appropriate output. See perrror(3) man page to understand better.
346 if (message
&& *message
)
347 pout("%s: %s\n",message
, errormessage
);
349 pout("%s\n",errormessage
);
351 else if (message
&& *message
)
352 pout("%s\n",message
);
357 // Check regular expression for non-portable features.
359 // POSIX extended regular expressions interpret unmatched ')' ordinary:
360 // "The close-parenthesis shall be considered special in this context
361 // only if matched with a preceding open-parenthesis."
363 // GNU libc and BSD libc support unmatched ')', Cygwin reports an error.
365 // POSIX extended regular expressions do not define empty subexpressions:
366 // "A vertical-line appearing first or last in an ERE, or immediately following
367 // a vertical-line or a left-parenthesis, or immediately preceding a
368 // right-parenthesis, produces undefined results."
370 // GNU libc and Cygwin support empty subexpressions, BSD libc reports an error.
372 static const char * check_regex(const char * pattern
)
377 for (int i
= 0; (c
= pattern
[i
]); i
++) {
387 if (pattern
[++i
] == '^')
391 while ((c
= pattern
[i
]) && c
!= ']')
398 // Check "(...)" nesting
401 else if (c
== ')' && --level
< 0)
402 return "Unmatched ')'";
404 // Check for leading/trailing '|' or "||", "|)", "|$", "(|", "^|"
406 if ( (c
== '|' && ( i
== 0 || !(c1
= pattern
[i
+1])
407 || c1
== '|' || c1
== ')' || c1
== '$'))
408 || ((c
== '(' || c
== '^') && pattern
[i
+1] == '|') )
409 return "Empty '|' subexpression";
412 return (const char *)0;
415 // Wrapper class for POSIX regex(3) or std::regex
417 #ifndef WITH_CXX11_REGEX
419 regular_expression::regular_expression()
421 memset(&m_regex_buf
, 0, sizeof(m_regex_buf
));
424 regular_expression::~regular_expression()
429 regular_expression::regular_expression(const regular_expression
& x
)
430 : m_pattern(x
.m_pattern
),
433 memset(&m_regex_buf
, 0, sizeof(m_regex_buf
));
437 regular_expression
& regular_expression::operator=(const regular_expression
& x
)
439 m_pattern
= x
.m_pattern
;
440 m_errmsg
= x
.m_errmsg
;
446 void regular_expression::free_buf()
448 if (nonempty(&m_regex_buf
, sizeof(m_regex_buf
))) {
449 regfree(&m_regex_buf
);
450 memset(&m_regex_buf
, 0, sizeof(m_regex_buf
));
454 void regular_expression::copy_buf(const regular_expression
& x
)
456 if (nonempty(&x
.m_regex_buf
, sizeof(x
.m_regex_buf
))) {
457 // There is no POSIX compiled-regex-copy command.
459 throw std::runtime_error(strprintf(
460 "Unable to recompile regular expression \"%s\": %s",
461 m_pattern
.c_str(), m_errmsg
.c_str()));
465 #endif // !WITH_CXX11_REGEX
467 regular_expression::regular_expression(const char * pattern
)
471 throw std::runtime_error(strprintf(
472 "error in regular expression \"%s\": %s",
473 m_pattern
.c_str(), m_errmsg
.c_str()));
476 bool regular_expression::compile(const char * pattern
)
478 #ifndef WITH_CXX11_REGEX
485 bool regular_expression::compile()
487 #ifdef WITH_CXX11_REGEX
489 m_regex
.assign(m_pattern
, std::regex_constants::extended
);
491 catch (std::regex_error
& ex
) {
492 m_errmsg
= ex
.what();
497 int errcode
= regcomp(&m_regex_buf
, m_pattern
.c_str(), REG_EXTENDED
);
500 regerror(errcode
, &m_regex_buf
, errmsg
, sizeof(errmsg
));
507 const char * errmsg
= check_regex(m_pattern
.c_str());
510 #ifdef WITH_CXX11_REGEX
511 m_regex
= std::regex();
522 bool regular_expression::full_match(const char * str
) const
524 #ifdef WITH_CXX11_REGEX
525 return std::regex_match(str
, m_regex
);
528 return ( !regexec(&m_regex_buf
, str
, 1, &range
, 0)
529 && range
.rm_so
== 0 && range
.rm_eo
== (int)strlen(str
));
533 bool regular_expression::execute(const char * str
, unsigned nmatch
, match_range
* pmatch
) const
535 #ifdef WITH_CXX11_REGEX
537 if (!std::regex_search(str
, m
, m_regex
))
539 unsigned sz
= m
.size();
540 for (unsigned i
= 0; i
< nmatch
; i
++) {
541 if (i
< sz
&& *m
[i
].first
) {
542 pmatch
[i
].rm_so
= m
[i
].first
- str
;
543 pmatch
[i
].rm_eo
= m
[i
].second
- str
;
546 pmatch
[i
].rm_so
= pmatch
[i
].rm_eo
= -1;
551 return !regexec(&m_regex_buf
, str
, nmatch
, pmatch
, 0);
555 // Splits an argument to the -t option that is assumed to be of the form
556 // "selective,%lld-%lld" (prefixes of "0" (for octal) and "0x"/"0X" (for hex)
557 // are allowed). The first long long int is assigned to *start and the second
558 // to *stop. Returns zero if successful and non-zero otherwise.
559 int split_selective_arg(char *s
, uint64_t *start
,
560 uint64_t *stop
, int *mode
)
563 if (!(s
= strchr(s
, ',')))
566 if (!isdigit((int)(*++s
))) {
568 if (!strncmp(s
, "redo", 4))
570 else if (!strncmp(s
, "next", 4))
572 else if (!strncmp(s
, "cont", 4))
585 // Last argument to strtoull (the base) is 0 meaning that decimal is assumed
586 // unless prefixes of "0" (for octal) or "0x"/"0X" (for hex) are used.
587 *start
= strtoull(s
, &tailptr
, 0);
590 if (!(!errno
&& (add
|| *s
== '-')))
592 if (!strcmp(s
, "-max")) {
593 *stop
= ~(uint64_t)0; // replaced by max LBA later
599 *stop
= strtoull(s
+1, &tailptr
, 0);
600 if (errno
|| *tailptr
!= '\0')
605 *stop
+= *start
; // -t select,N+M => -t select,N,(N+M-1)
610 // Returns true if region of memory contains non-zero entries
611 bool nonempty(const void * data
, int size
)
613 for (int i
= 0; i
< size
; i
++)
614 if (((const unsigned char *)data
)[i
])
619 // Copy not null terminated char array to null terminated string.
620 // Replace non-ascii characters. Remove leading and trailing blanks.
621 const char * format_char_array(char * str
, int strsize
, const char * chr
, int chrsize
)
624 while (b
< chrsize
&& chr
[b
] == ' ')
627 while (b
+n
< chrsize
&& chr
[b
+n
])
629 while (n
> 0 && chr
[b
+n
-1] == ' ')
635 for (int i
= 0; i
< n
; i
++) {
637 str
[i
] = (' ' <= c
&& c
<= '~' ? c
: '?');
644 // Format integer with thousands separator
645 const char * format_with_thousands_sep(char * str
, int strsize
, uint64_t val
,
646 const char * thousands_sep
/* = 0 */)
648 if (!thousands_sep
) {
651 setlocale(LC_ALL
, "");
652 const struct lconv
* currentlocale
= localeconv();
653 if (*(currentlocale
->thousands_sep
))
654 thousands_sep
= currentlocale
->thousands_sep
;
659 snprintf(num
, sizeof(num
), "%" PRIu64
, val
);
660 int numlen
= strlen(num
);
665 while (i
< numlen
&& (numlen
- i
) % 3 != 0 && j
< strsize
-1);
668 while (i
< numlen
&& j
< strsize
-1) {
669 j
+= snprintf(str
+j
, strsize
-j
, "%s%.3s", thousands_sep
, num
+i
);
676 // Format capacity with SI prefixes
677 const char * format_capacity(char * str
, int strsize
, uint64_t val
,
678 const char * decimal_point
/* = 0 */)
680 if (!decimal_point
) {
683 setlocale(LC_ALL
, "");
684 const struct lconv
* currentlocale
= localeconv();
685 if (*(currentlocale
->decimal_point
))
686 decimal_point
= currentlocale
->decimal_point
;
690 const unsigned factor
= 1000; // 1024 for KiB,MiB,...
691 static const char prefixes
[] = " KMGTP";
693 // Find d with val in [d, d*factor)
696 for (uint64_t d2
= d
* factor
; val
>= d2
; d2
*= factor
) {
698 if (++i
>= sizeof(prefixes
)-2)
703 uint64_t n
= val
/ d
;
705 snprintf(str
, strsize
, "%u B", (unsigned)n
);
706 else if (n
>= 100) // "123 xB"
707 snprintf(str
, strsize
, "%" PRIu64
" %cB", n
, prefixes
[i
]);
708 else if (n
>= 10) // "12.3 xB"
709 snprintf(str
, strsize
, "%" PRIu64
"%s%u %cB", n
, decimal_point
,
710 (unsigned)(((val
% d
) * 10) / d
), prefixes
[i
]);
712 snprintf(str
, strsize
, "%" PRIu64
"%s%02u %cB", n
, decimal_point
,
713 (unsigned)(((val
% d
) * 100) / d
), prefixes
[i
]);
718 // return (v)sprintf() formatted std::string
719 __attribute_format_printf(1, 0)
720 std::string
vstrprintf(const char * fmt
, va_list ap
)
723 vsnprintf(buf
, sizeof(buf
), fmt
, ap
);
724 buf
[sizeof(buf
)-1] = 0;
728 std::string
strprintf(const char * fmt
, ...)
730 va_list ap
; va_start(ap
, fmt
);
731 std::string str
= vstrprintf(fmt
, ap
);
736 #if defined(HAVE___INT128)
737 // Compiler supports '__int128'.
739 // Recursive 128-bit to string conversion function
740 static int snprint_uint128(char * str
, int strsize
, unsigned __int128 value
)
745 if (value
<= 0xffffffffffffffffULL
) {
746 // Print leading digits as 64-bit value
747 return snprintf(str
, (size_t)strsize
, "%" PRIu64
, (uint64_t)value
);
750 // Recurse to print leading digits
751 const uint64_t e19
= 10000000000000000000ULL; // 2^63 < 10^19 < 2^64
752 int len1
= snprint_uint128(str
, strsize
, value
/ e19
);
756 // Print 19 digits remainder as 64-bit value
757 int len2
= snprintf(str
+ (len1
< strsize
? len1
: strsize
- 1),
758 (size_t)(len1
< strsize
? strsize
- len1
: 1),
759 "%019" PRIu64
, (uint64_t)(value
% e19
) );
766 // Convert 128-bit unsigned integer provided as two 64-bit halves to a string.
767 const char * uint128_hilo_to_str(char * str
, int strsize
, uint64_t value_hi
, uint64_t value_lo
)
769 snprint_uint128(str
, strsize
, ((unsigned __int128
)value_hi
<< 64) | value_lo
);
773 #elif defined(HAVE_LONG_DOUBLE_WIDER_PRINTF)
774 // Compiler and *printf() support 'long double' which is wider than 'double'.
776 const char * uint128_hilo_to_str(char * str
, int strsize
, uint64_t value_hi
, uint64_t value_lo
)
778 snprintf(str
, strsize
, "%.0Lf", value_hi
* (0xffffffffffffffffULL
+ 1.0L) + value_lo
);
782 #else // !HAVE_LONG_DOUBLE_WIDER_PRINTF
783 // No '__int128' or 'long double' support, use 'double'.
785 const char * uint128_hilo_to_str(char * str
, int strsize
, uint64_t value_hi
, uint64_t value_lo
)
787 snprintf(str
, strsize
, "%.0f", value_hi
* (0xffffffffffffffffULL
+ 1.0) + value_lo
);
791 #endif // HAVE___INT128
793 // Runtime check of byte ordering, throws on error.
794 static void check_endianness()
797 // Force compile error if int type is not 32bit.
798 unsigned char c
[sizeof(int) == 4 ? 8 : -1];
800 } x
= {{1, 2, 3, 4, 5, 6, 7, 8}};
801 const uint64_t le
= 0x0807060504030201ULL
;
802 const uint64_t be
= 0x0102030405060708ULL
;
804 if (!( x
.i
== (isbigendian() ? be
: le
)
805 && sg_get_unaligned_le16(x
.c
) == (uint16_t)le
806 && sg_get_unaligned_be16(x
.c
+6) == (uint16_t)be
807 && sg_get_unaligned_le32(x
.c
) == (uint32_t)le
808 && sg_get_unaligned_be32(x
.c
+4) == (uint32_t)be
809 && sg_get_unaligned_le64(x
.c
) == le
810 && sg_get_unaligned_be64(x
.c
) == be
))
811 throw std::logic_error("CPU endianness does not match compile time test");
814 #ifndef HAVE_WORKING_SNPRINTF
815 // Some versions of (v)snprintf() don't append null char (MSVCRT.DLL),
816 // and/or return -1 on output truncation (glibc <= 2.0.6).
817 // Below are sane replacements substituted by #define in utility.h.
820 #if defined(_WIN32) && defined(_MSC_VER)
821 #define vsnprintf _vsnprintf
824 int safe_vsnprintf(char *buf
, int size
, const char *fmt
, va_list ap
)
829 i
= vsnprintf(buf
, size
, fmt
, ap
);
830 if (0 <= i
&& i
< size
)
833 return strlen(buf
); // Note: cannot detect for overflow, not necessary here.
836 int safe_snprintf(char *buf
, int size
, const char *fmt
, ...)
840 i
= safe_vsnprintf(buf
, size
, fmt
, ap
);
845 static void check_snprintf() {}
847 #elif defined(__GNUC__) && (__GNUC__ >= 7)
849 // G++ 7+: Assume sane implementation and avoid -Wformat-truncation warning
850 static void check_snprintf() {}
854 static void check_snprintf()
856 char buf
[] = "ABCDEFGHI";
857 int n1
= snprintf(buf
, 8, "123456789");
858 int n2
= snprintf(buf
, 0, "X");
859 if (!(!strcmp(buf
, "1234567") && n1
== 9 && n2
== 1))
860 throw std::logic_error("Function snprintf() does not conform to C99");
863 #endif // HAVE_WORKING_SNPRINTF
865 // Runtime check of ./configure result, throws on error.