smartmontools SVN Rev 3317
Utility to control and monitor storage systems with "S.M.A.R.T."
utility.h
Go to the documentation of this file.
00001 /*
00002  * utility.h
00003  *
00004  * Home page of code is: http://smartmontools.sourceforge.net
00005  *
00006  * Copyright (C) 2002-11 Bruce Allen <smartmontools-support@lists.sourceforge.net>
00007  * Copyright (C) 2008-12 Christian Franke <smartmontools-support@lists.sourceforge.net>
00008  * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
00009  *
00010  * This program is free software; you can redistribute it and/or modify
00011  * it under the terms of the GNU General Public License as published by
00012  * the Free Software Foundation; either version 2, or (at your option)
00013  * any later version.
00014  *
00015  * You should have received a copy of the GNU General Public License
00016  * (for example COPYING); If not, see <http://www.gnu.org/licenses/>.
00017  *
00018  * This code was originally developed as a Senior Thesis by Michael Cornwell
00019  * at the Concurrent Systems Laboratory (now part of the Storage Systems
00020  * Research Center), Jack Baskin School of Engineering, University of
00021  * California, Santa Cruz. http://ssrc.soe.ucsc.edu/
00022  *
00023  */
00024 
00025 #ifndef UTILITY_H_
00026 #define UTILITY_H_
00027 
00028 #define UTILITY_H_CVSID "$Id: utility.h 3719 2012-12-03 21:19:33Z chrfranke $"
00029 
00030 #include <time.h>
00031 #include <sys/types.h> // for regex.h (according to POSIX)
00032 #include <regex.h>
00033 #include <stdarg.h>
00034 #include <stdio.h>
00035 #include <string.h>
00036 #include <string>
00037 
00038 #ifndef __GNUC__
00039 #define __attribute_format_printf(x, y)  /**/
00040 #elif defined(__MINGW32__) && __USE_MINGW_ANSI_STDIO
00041 // Check format of __mingw_*printf() instead of MSVCRT.DLL:*printf()
00042 #define __attribute_format_printf(x, y)  __attribute__((format (gnu_printf, x, y)))
00043 #define HAVE_WORKING_SNPRINTF 1
00044 #else
00045 #define __attribute_format_printf(x, y)  __attribute__((format (printf, x, y)))
00046 #endif
00047 
00048 // Make version information string
00049 std::string format_version_info(const char * prog_name, bool full = false);
00050 
00051 // return (v)sprintf() formated std::string
00052 std::string strprintf(const char * fmt, ...)
00053     __attribute_format_printf(1, 2);
00054 std::string vstrprintf(const char * fmt, va_list ap);
00055 
00056 // Return true if STR starts with PREFIX
00057 inline bool str_starts_with(const char * str, const char * prefix)
00058   { return !strncmp(str, prefix, strlen(prefix)); }
00059 
00060 inline bool str_starts_with(const std::string & str, const char * prefix)
00061   { return !strncmp(str.c_str(), prefix, strlen(prefix)); }
00062 
00063 #ifndef HAVE_WORKING_SNPRINTF
00064 // Substitute by safe replacement functions
00065 int safe_snprintf(char *buf, int size, const char *fmt, ...)
00066     __attribute_format_printf(3, 4);
00067 int safe_vsnprintf(char *buf, int size, const char *fmt, va_list ap);
00068 #define snprintf  safe_snprintf
00069 #define vsnprintf safe_vsnprintf
00070 #endif
00071 
00072 #ifndef HAVE_STRTOULL
00073 // Replacement for missing strtoull() (Linux with libc < 6, MSVC)
00074 uint64_t strtoull(const char * p, char * * endp, int base);
00075 #endif
00076 
00077 // Utility function prints current date and time and timezone into a
00078 // character buffer of length>=64.  All the fuss is needed to get the
00079 // right timezone info (sigh).
00080 #define DATEANDEPOCHLEN 64
00081 void dateandtimezone(char *buffer);
00082 // Same, but for time defined by epoch tval
00083 void dateandtimezoneepoch(char *buffer, time_t tval);
00084 
00085 // like printf() except that we can control it better. Note --
00086 // although the prototype is given here in utility.h, the function
00087 // itself is defined differently in smartctl and smartd.  So the
00088 // function definition(s) are in smartd.c and in smartctl.c.
00089 void pout(const char *fmt, ...)  
00090     __attribute_format_printf(1, 2);
00091 
00092 // replacement for perror() with redirected output.
00093 void syserror(const char *message);
00094 
00095 // Function for processing -r option in smartctl and smartd
00096 int split_report_arg(char *s, int *i);
00097 
00098 // Function for processing -t selective... option in smartctl
00099 int split_selective_arg(char *s, uint64_t *start, uint64_t *stop, int *mode);
00100 
00101 
00102 // Guess device type (ata or scsi) based on device name 
00103 // Guessing will now use Controller Type defines below
00104 
00105 // Moved to C++ interface
00106 //int guess_device_type(const char * dev_name);
00107 
00108 // Create and return the list of devices to probe automatically
00109 // if the DEVICESCAN option is in the smartd config file
00110 // Moved to C++ interface
00111 //int make_device_names (char ***devlist, const char* name);
00112 
00113 // Replacement for exit(status)
00114 // (exit is not compatible with C++ destructors)
00115 #define EXIT(status) { throw (int)(status); }
00116 
00117 
00118 #ifdef OLD_INTERFACE
00119 
00120 // replacement for calloc() that tracks memory usage
00121 void *Calloc(size_t nmemb, size_t size);
00122 
00123 // Utility function to free memory
00124 void *FreeNonZero1(void* address, int size, int whatline, const char* file);
00125 
00126 // Typesafe version of above
00127 template <class T>
00128 inline T * FreeNonZero(T * address, int size, int whatline, const char* file)
00129   { return (T *)FreeNonZero1((void *)address, size, whatline, file); }
00130 
00131 // A custom version of strdup() that keeps track of how much memory is
00132 // being allocated. If mustexist is set, it also throws an error if we
00133 // try to duplicate a NULL string.
00134 char *CustomStrDup(const char *ptr, int mustexist, int whatline, const char* file);
00135 
00136 // To help with memory checking.  Use when it is known that address is
00137 // NOT null.
00138 void *CheckFree1(void *address, int whatline, const char* file);
00139 
00140 // Typesafe version of above
00141 template <class T>
00142 inline T * CheckFree(T * address, int whatline, const char* file)
00143   { return (T *)CheckFree1((void *)address, whatline, file); }
00144 
00145 #endif // OLD_INTERFACE
00146 
00147 // Compile time check of byte ordering
00148 // (inline const function allows compiler to remove dead code)
00149 inline bool isbigendian()
00150 {
00151 #ifdef WORDS_BIGENDIAN
00152   return true;
00153 #else
00154   return false;
00155 #endif
00156 }
00157 
00158 // Runtime check of byte ordering, throws if different from isbigendian().
00159 void check_endianness();
00160 
00161 // This value follows the peripheral device type value as defined in
00162 // SCSI Primary Commands, ANSI INCITS 301:1997.  It is also used in
00163 // the ATA standard for packet devices to define the device type.
00164 const char *packetdevicetype(int type);
00165 
00166 // Moved to C++ interface
00167 //int deviceopen(const char *pathname, char *type);
00168 
00169 //int deviceclose(int fd);
00170 
00171 // Optional functions of os_*.c
00172 #ifdef HAVE_GET_OS_VERSION_STR
00173 // Return build host and OS version as static string
00174 //const char * get_os_version_str(void);
00175 #endif
00176 
00177 // returns true if any of the n bytes are nonzero, else zero.
00178 bool nonempty(const void * data, int size);
00179 
00180 // needed to fix glibc bug
00181 void FixGlibcTimeZoneBug();
00182 
00183 // Format integer with thousands separator
00184 const char * format_with_thousands_sep(char * str, int strsize, uint64_t val,
00185                                        const char * thousands_sep = 0);
00186 
00187 // Format capacity with SI prefixes
00188 const char * format_capacity(char * str, int strsize, uint64_t val,
00189                              const char * decimal_point = 0);
00190 
00191 // Wrapper class for a raw data buffer
00192 class raw_buffer
00193 {
00194 public:
00195   explicit raw_buffer(unsigned sz, unsigned char val = 0)
00196     : m_data(new unsigned char[sz]),
00197       m_size(sz)
00198     { memset(m_data, val, m_size); }
00199 
00200   ~raw_buffer()
00201     { delete [] m_data; }
00202 
00203   unsigned size() const
00204     { return m_size; }
00205 
00206   unsigned char * data()
00207     { return m_data; }
00208   const unsigned char * data() const
00209     { return m_data; }
00210 
00211 private:
00212   unsigned char * m_data;
00213   unsigned m_size;
00214 
00215   raw_buffer(const raw_buffer &);
00216   void operator=(const raw_buffer &);
00217 };
00218 
00219 /// Wrapper class for FILE *.
00220 class stdio_file
00221 {
00222 public:
00223   explicit stdio_file(FILE * f = 0, bool owner = false)
00224     : m_file(f), m_owner(owner) { }
00225 
00226   stdio_file(const char * name, const char * mode)
00227     : m_file(fopen(name, mode)), m_owner(true) { }
00228 
00229   ~stdio_file()
00230     {
00231       if (m_file && m_owner)
00232         fclose(m_file);
00233     }
00234 
00235   bool open(const char * name, const char * mode)
00236     {
00237       m_file = fopen(name, mode);
00238       m_owner = true;
00239       return !!m_file;
00240     }
00241 
00242   void open(FILE * f, bool owner = false)
00243     {
00244       m_file = f;
00245       m_owner = owner;
00246     }
00247 
00248   bool close()
00249     {
00250       if (!m_file)
00251         return true;
00252       bool ok = !ferror(m_file);
00253       if (fclose(m_file))
00254         ok = false;
00255       m_file = 0;
00256       return ok;
00257     }
00258 
00259   operator FILE * ()
00260     { return m_file; }
00261 
00262   bool operator!() const
00263     { return !m_file; }
00264 
00265 private:
00266   FILE * m_file;
00267   bool m_owner;
00268 
00269   stdio_file(const stdio_file &);
00270   void operator=(const stdio_file &);
00271 };
00272 
00273 /// Wrapper class for regex(3).
00274 /// Supports copy & assignment and is compatible with STL containers.
00275 class regular_expression
00276 {
00277 public:
00278   // Construction & assignment
00279   regular_expression();
00280 
00281   regular_expression(const char * pattern, int flags,
00282                      bool throw_on_error = true);
00283 
00284   ~regular_expression();
00285 
00286   regular_expression(const regular_expression & x);
00287 
00288   regular_expression & operator=(const regular_expression & x);
00289 
00290   /// Set and compile new pattern, return false on error.
00291   bool compile(const char * pattern, int flags);
00292 
00293   // Get pattern from last compile().
00294   const char * get_pattern() const
00295     { return m_pattern.c_str(); }
00296 
00297   /// Get error message from last compile().
00298   const char * get_errmsg() const
00299     { return m_errmsg.c_str(); }
00300 
00301   // Return true if pattern is not set or bad.
00302   bool empty() const
00303     { return (m_pattern.empty() || !m_errmsg.empty()); }
00304 
00305   /// Return true if substring matches pattern
00306   bool match(const char * str, int flags = 0) const
00307     { return !regexec(&m_regex_buf, str, 0, (regmatch_t*)0, flags); }
00308 
00309   /// Return true if full string matches pattern
00310   bool full_match(const char * str, int flags = 0) const
00311     {
00312       regmatch_t range;
00313       return (   !regexec(&m_regex_buf, str, 1, &range, flags)
00314               && range.rm_so == 0 && range.rm_eo == (int)strlen(str));
00315     }
00316 
00317   /// Return true if substring matches pattern, fill regmatch_t array.
00318   bool execute(const char * str, unsigned nmatch, regmatch_t * pmatch, int flags = 0) const
00319     { return !regexec(&m_regex_buf, str, nmatch, pmatch, flags); }
00320 
00321 private:
00322   std::string m_pattern;
00323   int m_flags;
00324   regex_t m_regex_buf;
00325   std::string m_errmsg;
00326 
00327   void free_buf();
00328   void copy(const regular_expression & x);
00329   bool compile();
00330 };
00331 
00332 #ifdef _WIN32
00333 // Get exe directory
00334 //(implemented in os_win32.cpp)
00335 std::string get_exe_dir();
00336 #endif
00337 
00338 
00339 #ifdef OLD_INTERFACE
00340 // remaining controller types in old interface modules
00341 #define CONTROLLER_UNKNOWN              0x00
00342 #define CONTROLLER_ATA                  0x01
00343 #define CONTROLLER_SCSI                 0x02
00344 #endif
00345 
00346 #endif
00347