X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=utility.h;h=02c913bf7320c06f6188852c2482ed936fe385e5;hb=7af9336546f5d8f23d8760b67b3d835773e52f04;hp=2b23d51e04d1c00505c13d752e1296b0f01e3927;hpb=cdafb78b23fff3ab7270db93413558e6cf05e2d2;p=mirror_smartmontools-debian.git diff --git a/utility.h b/utility.h index 2b23d51..02c913b 100644 --- a/utility.h +++ b/utility.h @@ -1,9 +1,10 @@ /* * utility.h * - * Home page of code is: http://smartmontools.sourceforge.net + * Home page of code is: http://www.smartmontools.org * - * Copyright (C) 2002-6 Bruce Allen + * Copyright (C) 2002-11 Bruce Allen + * Copyright (C) 2008-15 Christian Franke * Copyright (C) 2000 Michael Cornwell * * This program is free software; you can redistribute it and/or modify @@ -12,8 +13,7 @@ * any later version. * * You should have received a copy of the GNU General Public License - * (for example COPYING); if not, write to the Free - * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + * (for example COPYING); If not, see . * * This code was originally developed as a Senior Thesis by Michael Cornwell * at the Concurrent Systems Laboratory (now part of the Storage Systems @@ -25,21 +25,55 @@ #ifndef UTILITY_H_ #define UTILITY_H_ -#define UTILITY_H_CVSID "$Id: utility.h,v 1.46 2006/08/25 06:06:25 sxzzsf Exp $\n" +#define UTILITY_H_CVSID "$Id: utility.h 4145 2015-10-17 12:01:38Z chrfranke $" #include #include // for regex.h (according to POSIX) #include +#include +#include +#include +#include + +#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 -#include -int safe_snprintf(char *buf, int size, const char *fmt, ...); +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). @@ -48,143 +82,230 @@ void dateandtimezone(char *buffer); // Same, but for time defined by epoch tval void dateandtimezoneepoch(char *buffer, time_t tval); -// utility function for printing out CVS strings -#define CVSMAXLEN 1024 -void printone(char *block, const char *cvsid); - // 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. -#ifndef __GNUC__ -#define __attribute__(x) /* nothing */ -#endif void pout(const char *fmt, ...) - __attribute__ ((format (printf, 1, 2))); + __attribute_format_printf(1, 2); // replacement for perror() with redirected output. void syserror(const char *message); -// Prints a warning message for a failed regular expression compilation from -// regcomp(). -void printregexwarning(int errcode, regex_t *compiled); - -// A wrapper for regcomp(). Returns zero for success, non-zero otherwise. -int compileregex(regex_t *compiled, const char *pattern, int cflags); - // Function for processing -r option in smartctl and smartd int split_report_arg(char *s, int *i); -// Function for processing -c option in smartctl and smartd -int split_report_arg2(char *s, int *i); -// Function for processing -t selective... option in smartctl -int split_selective_arg(char *s, uint64_t *start, uint64_t *stop); - - -// Guess device type (ata or scsi) based on device name -// Guessing will now use Controller Type defines below - -int guess_device_type(const char * dev_name); -// Create and return the list of devices to probe automatically -// if the DEVICESCAN option is in the smartd config file -int make_device_names (char ***devlist, const char* name); +// 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); } -#define EXIT(x) { exitstatus = (x); exit((x)); } -// replacement for calloc() that tracks memory usage -void *Calloc(size_t nmemb, size_t size); +#ifdef OLD_INTERFACE // Utility function to free memory -void *FreeNonZero1(void* address, int size, int whatline, const char* file); - -// Typesafe version of above -template -inline T * FreeNonZero(T * address, int size, int whatline, const char* file) - { return (T *)FreeNonZero1((void *)address, size, whatline, file); } +void *FreeNonZero(void* address, int size, int whatline, const char* file); // A custom version of strdup() that keeps track of how much memory is // being allocated. If mustexist is set, it also throws an error if we // try to duplicate a NULL string. -char *CustomStrDup(char *ptr, int mustexist, int whatline, const char* file); - -// To help with memory checking. Use when it is known that address is -// NOT null. -void *CheckFree1(void *address, int whatline, const char* file); - -// Typesafe version of above -template -inline T * CheckFree(T * address, int whatline, const char* file) - { return (T *)CheckFree1((void *)address, whatline, file); } - -// This function prints either to stdout or to the syslog as needed - -// [From GLIBC Manual: Since the prototype doesn't specify types for -// optional arguments, in a call to a variadic function the default -// argument promotions are performed on the optional argument -// values. This means the objects of type char or short int (whether -// signed or not) are promoted to either int or unsigned int, as -// appropriate.] -void PrintOut(int priority, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); +char *CustomStrDup(const char *ptr, int mustexist, int whatline, const char* file); + +#endif // OLD_INTERFACE + +// 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 +} -// run time, determine byte ordering -int isbigendian(); +// 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); -int deviceopen(const char *pathname, char *type); - -int deviceclose(int fd); - -// Optional functions of os_*.c -#ifdef HAVE_GET_OS_VERSION_STR -// Return build host and OS version as static string -const char * get_os_version_str(void); -#endif - -// returns 1 if any of the n bytes are nonzero, else zero. -int nonempty(unsigned char *testarea,int n); +// 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(); -// convert time in msec to a text string -void MsecToText(unsigned int msec, char *txt); - -// Exit codes -#define EXIT_BADCMD 1 // command line did not parse -#define EXIT_BADCONF 2 // syntax error in config file -#define EXIT_STARTUP 3 // problem forking daemon -#define EXIT_PID 4 // problem creating pid file -#define EXIT_NOCONF 5 // config file does not exist -#define EXIT_READCONF 6 // config file exists but cannot be read - -#define EXIT_NOMEM 8 // out of memory -#define EXIT_BADCODE 10 // internal error - should NEVER happen - -#define EXIT_BADDEV 16 // we can't monitor this device -#define EXIT_NODEV 17 // no devices to monitor - -#define EXIT_SIGNAL 254 // abort on signal - +// 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 -// macros to control printing -#define PRINT_ON(control) {if (control->printing_switchable) control->dont_print=0;} -#define PRINT_OFF(control) {if (control->printing_switchable) control->dont_print=1;} -// possible values for controller_type in extern.h +#ifdef OLD_INTERFACE +// remaining controller types in old interface modules #define CONTROLLER_UNKNOWN 0x00 #define CONTROLLER_ATA 0x01 #define CONTROLLER_SCSI 0x02 -#define CONTROLLER_3WARE 0x03 // set by -d option, but converted to one of three types below -#define CONTROLLER_3WARE_678K 0x04 // NOT set by guess_device_type() -#define CONTROLLER_3WARE_9000_CHAR 0x05 // set by guess_device_type() -#define CONTROLLER_3WARE_678K_CHAR 0x06 // set by guess_device_type() -#define CONTROLLER_MARVELL_SATA 0x07 // SATA drives behind Marvell controllers -#define CONTROLLER_SAT 0x08 // SATA device behind a SCSI ATA Translation (SAT) layer -#define CONTROLLER_HPT 0x09 // SATA drives behind HighPoint Raid controllers +#endif #endif +