|
smartmontools SVN Rev 3317
Utility to control and monitor storage systems with "S.M.A.R.T."
|
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
1.7.4