4
4
* Home page of code is: http://smartmontools.sourceforge.net
6
* Copyright (C) 2002-8 Bruce Allen <smartmontools-support@lists.sourceforge.net>
6
* Copyright (C) 2002-10 Bruce Allen <smartmontools-support@lists.sourceforge.net>
7
* Copyright (C) 2008-10 Christian Franke <smartmontools-support@lists.sourceforge.net>
7
8
* Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
9
10
* This program is free software; you can redistribute it and/or modify
39
40
#include <mbstring.h> // _mbsinc()
42
45
#include "config.h"
46
#include "svnversion.h"
44
48
#include "utility.h"
46
// Any local header files should be represented by a CVSIDX just below.
47
const char* utility_c_cvsid="$Id: utility.cpp,v 1.65 2008/03/04 22:09:47 ballen4705 Exp $"
48
CONFIG_H_CVSID INT64_H_CVSID UTILITY_H_CVSID;
51
#include "dev_interface.h"
53
const char * utility_cpp_cvsid = "$Id: utility.cpp 3022 2010-01-01 17:02:00Z chrfranke $"
54
UTILITY_H_CVSID INT64_H_CVSID;
50
56
const char * packet_types[] = {
51
57
"Direct-access (disk)",
70
76
const char *reportbug="Please report this bug to the Smartmontools developers at " PACKAGE_BUGREPORT ".\n";
73
// hang on to exit code, so we can make use of more generic 'atexit()'
74
// functionality and still check our exit code
77
79
// command-line argument: are we running in debug mode?.
78
80
unsigned char debugmode = 0;
82
// BUILD_INFO can be provided by package maintainers
84
#define BUILD_INFO "(local build)"
87
// Make version information string
88
std::string format_version_info(const char * prog_name, bool full /*= false*/)
90
std::string info = strprintf(
91
"%s "PACKAGE_VERSION" "SMARTMONTOOLS_SVN_DATE" r"SMARTMONTOOLS_SVN_REV
92
" [%s] "BUILD_INFO"\n"
93
"Copyright (C) 2002-10 by Bruce Allen, http://smartmontools.sourceforge.net\n",
94
prog_name, smi()->get_os_version_str().c_str()
101
"%s comes with ABSOLUTELY NO WARRANTY. This is free\n"
102
"software, and you are welcome to redistribute it under\n"
103
"the terms of the GNU General Public License Version 2.\n"
104
"See http://www.gnu.org for further details.\n"
109
"smartmontools release "PACKAGE_VERSION
110
" dated "SMARTMONTOOLS_RELEASE_DATE" at "SMARTMONTOOLS_RELEASE_TIME"\n"
111
"smartmontools SVN rev "SMARTMONTOOLS_SVN_REV
112
" dated "SMARTMONTOOLS_SVN_DATE" at "SMARTMONTOOLS_SVN_TIME"\n"
113
"smartmontools build host: "SMARTMONTOOLS_BUILD_HOST"\n"
114
"smartmontools build configured: "SMARTMONTOOLS_CONFIGURE_DATE "\n"
115
"%s compile dated "__DATE__" at "__TIME__"\n"
116
"smartmontools configure arguments: ",
119
info += (sizeof(SMARTMONTOOLS_CONFIGURE_ARGS) > 1 ?
120
SMARTMONTOOLS_CONFIGURE_ARGS : "[no arguments given]");
81
126
// Solaris only: Get site-default timezone. This is called from
82
127
// UpdateTimezone() when TZ environment variable is unset at startup.
288
// These are two utility functions for printing CVS IDs. Massagecvs()
289
// returns distance that it has moved ahead in the input string
290
int massagecvs(char *out, const char *cvsid){
291
char *copy,*filename,*date,*version;
293
const char delimiters[] = " ,$";
295
// make a copy on the heap, go to first token,
296
if (!(copy=strdup(cvsid)))
299
if (!(filename=strtok(copy, delimiters)))
302
// move to first instance of "Id:"
303
while (strcmp(filename,"Id:"))
304
if (!(filename=strtok(NULL, delimiters)))
307
// get filename, skip "v", get version and date
308
if (!( filename=strtok(NULL, delimiters) ) ||
309
!( strtok(NULL, delimiters) ) ||
310
!( version=strtok(NULL, delimiters) ) ||
311
!( date=strtok(NULL, delimiters) ) )
314
sprintf(out,"%-16s revision: %-5s date: %-15s", filename, version, date);
315
retVal = (date-copy)+strlen(date);
322
// prints a single set of CVS ids
323
void printone(char *block, const char *cvsid){
324
char strings[CVSMAXLEN];
325
const char *here=cvsid;
326
int bi=0, len=strlen(cvsid)+1;
328
// check that the size of the output block is sufficient
329
if (len>=CVSMAXLEN) {
330
pout("CVSMAXLEN=%d must be at least %d\n",CVSMAXLEN,len+1);
334
// loop through the different strings
335
while (bi<CVSMAXLEN && (len=massagecvs(strings,here))){
336
bi+=snprintf(block+bi,CVSMAXLEN-bi,"%s %s\n",(bi==0?"Module:":" uses:"),strings);
343
333
// A replacement for perror() that sends output to our choice of
344
334
// printing. If errno not set then just print message.
345
335
void syserror(const char *message){
364
// Prints a warning message for a failed regular expression compilation from
366
void printregexwarning(int errcode, regex_t *compiled){
367
size_t length = regerror(errcode, compiled, NULL, 0);
368
char *buffer = (char*)malloc(length);
370
pout("Out of memory in printregexwarning()\n");
373
regerror(errcode, compiled, buffer, length);
374
pout("%s\n", buffer);
379
354
// POSIX extended regular expressions interpret unmatched ')' ordinary:
380
355
// "The close-parenthesis shall be considered special in this context
381
356
// only if matched with a preceding open-parenthesis."
401
// A wrapper for regcomp(). Returns zero for success, non-zero otherwise.
402
int compileregex(regex_t *compiled, const char *pattern, int cflags)
406
if ( (errorcode = regcomp(compiled, pattern, cflags))
407
|| check_regex_nesting(pattern) < 0 ) {
408
pout("Internal error: unable to compile regular expression \"%s\" ", pattern);
410
printregexwarning(errorcode, compiled);
412
pout("Unmatched ')'\n");
413
pout("Please inform smartmontools developers at " PACKAGE_BUGREPORT "\n");
377
// Wrapper class for regex(3)
379
regular_expression::regular_expression()
382
memset(&m_regex_buf, 0, sizeof(m_regex_buf));
385
regular_expression::regular_expression(const char * pattern, int flags)
387
memset(&m_regex_buf, 0, sizeof(m_regex_buf));
388
compile(pattern, flags);
391
regular_expression::~regular_expression()
396
regular_expression::regular_expression(const regular_expression & x)
398
memset(&m_regex_buf, 0, sizeof(m_regex_buf));
402
regular_expression & regular_expression::operator=(const regular_expression & x)
409
void regular_expression::free_buf()
411
if (nonempty(&m_regex_buf, sizeof(m_regex_buf))) {
412
regfree(&m_regex_buf);
413
memset(&m_regex_buf, 0, sizeof(m_regex_buf));
417
void regular_expression::copy(const regular_expression & x)
419
m_pattern = x.m_pattern;
421
m_errmsg = x.m_errmsg;
423
if (!m_pattern.empty() && m_errmsg.empty()) {
424
// There is no POSIX compiled-regex-copy command.
426
throw std::runtime_error(strprintf(
427
"Unable to recompile regular expression \"%s\": %s",
428
m_pattern.c_str(), m_errmsg.c_str()));
432
bool regular_expression::compile(const char * pattern, int flags)
440
bool regular_expression::compile()
442
int errcode = regcomp(&m_regex_buf, m_pattern.c_str(), m_flags);
445
regerror(errcode, &m_regex_buf, errmsg, sizeof(errmsg));
451
if (check_regex_nesting(m_pattern.c_str()) < 0) {
452
m_errmsg = "Unmatched ')'";
419
461
// Splits an argument to the -r option into a name part and an (optional)
467
509
#ifndef HAVE_STRTOULL
468
// Replacement for missing strtoull() (Linux with libc < 6, MSVC 6.0)
469
// Functionality reduced to split_selective_arg()'s requirements.
510
// Replacement for missing strtoull() (Linux with libc < 6, MSVC)
511
// Functionality reduced to requirements of smartd and split_selective_arg().
471
static uint64_t strtoull(const char * p, char * * endp, int base)
513
uint64_t strtoull(const char * p, char * * endp, int base)
473
515
uint64_t result, maxres;
478
if (p[i] == 'x' || p[i] == 'X') {
521
if (p[i] == 'x' || p[i] == 'X') {
489
533
maxres = ~(uint64_t)0 / (unsigned)base;
616
#define EXIT_NOMEM 8 // out of memory
617
#define EXIT_BADCODE 10 // internal error - should NEVER happen
568
619
int64_t bytes = 0;
569
621
// Helps debugging. If the second argument is non-negative, then
570
622
// decrement bytes by that amount. Else decrement bytes by (one plus)
571
623
// length of null terminated string.
637
// Returns nonzero if region of memory contains non-zero entries
638
int nonempty(unsigned char *testarea,int n){
689
#endif // OLD_INTERFACE
692
// Returns true if region of memory contains non-zero entries
693
bool nonempty(const void * data, int size)
695
for (int i = 0; i < size; i++)
696
if (((const unsigned char *)data)[i])
730
// return (v)sprintf() formatted std::string
732
std::string vstrprintf(const char * fmt, va_list ap)
735
vsnprintf(buf, sizeof(buf), fmt, ap);
736
buf[sizeof(buf)-1] = 0;
740
std::string strprintf(const char * fmt, ...)
742
va_list ap; va_start(ap, fmt);
743
std::string str = vstrprintf(fmt, ap);
676
749
#ifndef HAVE_WORKING_SNPRINTF
677
750
// Some versions of (v)snprintf() don't append null char on overflow (MSVCRT.DLL),