⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 utility.cpp

📁 硬盘各项性能的测试,如温度容量版本健康度型号
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/* * utility.cpp * * Home page of code is: http://smartmontools.sourceforge.net * * Copyright (C) 2002-8 Bruce Allen <smartmontools-support@lists.sourceforge.net> * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * 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. * * This code was originally developed as a Senior Thesis by Michael Cornwell * at the Concurrent Systems Laboratory (now part of the Storage Systems * Research Center), Jack Baskin School of Engineering, University of * California, Santa Cruz. http://ssrc.soe.ucsc.edu/ * */// THIS FILE IS INTENDED FOR UTILITY ROUTINES THAT ARE APPLICABLE TO// BOTH SCSI AND ATA DEVICES, AND THAT MAY BE USED IN SMARTD,// SMARTCTL, OR BOTH.#include <stdio.h>#include <string.h>#include <time.h>#include <errno.h>#include <stdlib.h>#include <ctype.h>#include <syslog.h>#include <stdarg.h>#include <sys/stat.h>#ifdef _WIN32#include <mbstring.h> // _mbsinc()#endif#include "config.h"#include "int64.h"#include "utility.h"// Any local header files should be represented by a CVSIDX just below.const char* utility_c_cvsid="$Id: utility.cpp,v 1.65 2008/03/04 22:09:47 ballen4705 Exp $"CONFIG_H_CVSID INT64_H_CVSID UTILITY_H_CVSID;const char * packet_types[] = {        "Direct-access (disk)",        "Sequential-access (tape)",        "Printer",        "Processor",        "Write-once (optical disk)",        "CD/DVD",        "Scanner",        "Optical memory (optical disk)",        "Medium changer",        "Communications",        "Graphic arts pre-press (10)",        "Graphic arts pre-press (11)",        "Array controller",        "Enclosure services",        "Reduced block command (simplified disk)",        "Optical card reader/writer"};// Whenever exit() status is EXIT_BADCODE, please print this messageconst char *reportbug="Please report this bug to the Smartmontools developers at " PACKAGE_BUGREPORT ".\n";// hang on to exit code, so we can make use of more generic 'atexit()'// functionality and still check our exit codeint exitstatus = 0;// command-line argument: are we running in debug mode?.unsigned char debugmode = 0;// Solaris only: Get site-default timezone. This is called from// UpdateTimezone() when TZ environment variable is unset at startup.#if defined (__SVR4) && defined (__sun)static const char *TIMEZONE_FILE = "/etc/TIMEZONE";static char *ReadSiteDefaultTimezone(){  FILE *fp;  char buf[512], *tz;  int n;  tz = NULL;  fp = fopen(TIMEZONE_FILE, "r");  if(fp == NULL) return NULL;  while(fgets(buf, sizeof(buf), fp)) {    if (strncmp(buf, "TZ=", 3))    // searches last "TZ=" line      continue;    n = strlen(buf) - 1;    if (buf[n] == '\n') buf[n] = 0;    if (tz) free(tz);    tz = strdup(buf);  }  fclose(fp);  return tz;}#endif// Make sure that this executable is aware if the user has changed the// time-zone since the last time we polled devices. The cannonical// example is a user who starts smartd on a laptop, then flies across// time-zones with a laptop, and then changes the timezone, WITHOUT// restarting smartd. This is a work-around for a bug in// GLIBC. Yuk. See bug number 48184 at http://bugs.debian.org and// thanks to Ian Redfern for posting a workaround.// Please refer to the smartd manual page, in the section labeled LOG// TIMESTAMP TIMEZONE.void FixGlibcTimeZoneBug(){#if __GLIBC__    if (!getenv("TZ")) {    putenv("TZ=GMT");    tzset();    putenv("TZ");    tzset();  }#elif _WIN32  if (!getenv("TZ")) {    putenv("TZ=GMT");    tzset();    putenv("TZ=");  // empty value removes TZ, putenv("TZ") does nothing    tzset();  }#elif defined (__SVR4) && defined (__sun)  // In Solaris, putenv("TZ=") sets null string and invalid timezone.  // putenv("TZ") does nothing.  With invalid TZ, tzset() do as if  // TZ=GMT.  With TZ unset, /etc/TIMEZONE will be read only _once_ at  // first tzset() call.  Conclusion: Unlike glibc, dynamic  // configuration of timezone can be done only by changing actual  // value of TZ environment value.  enum tzstate { NOT_CALLED_YET, USER_TIMEZONE, TRACK_TIMEZONE };  static enum tzstate state = NOT_CALLED_YET;  static struct stat prev_stat;  static char *prev_tz;  struct stat curr_stat;  char *curr_tz;  if(state == NOT_CALLED_YET) {    if(getenv("TZ")) {      state = USER_TIMEZONE; // use supplied timezone    } else {      state = TRACK_TIMEZONE;      if(stat(TIMEZONE_FILE, &prev_stat)) {	state = USER_TIMEZONE;	// no TZ, no timezone file; use GMT forever      } else {	prev_tz = ReadSiteDefaultTimezone(); // track timezone file change	if(prev_tz) putenv(prev_tz);      }    }    tzset();  } else if(state == TRACK_TIMEZONE) {    if(stat(TIMEZONE_FILE, &curr_stat) == 0       && (curr_stat.st_ctime != prev_stat.st_ctime	    || curr_stat.st_mtime != prev_stat.st_mtime)) {      // timezone file changed      curr_tz = ReadSiteDefaultTimezone();      if(curr_tz) {	putenv(curr_tz);	if(prev_tz) free(prev_tz);	prev_tz = curr_tz; prev_stat = curr_stat;       }    }    tzset();  }#endif  // OTHER OS/LIBRARY FIXES SHOULD GO HERE, IF DESIRED.  PLEASE TRY TO  // KEEP THEM INDEPENDENT.  return;}#ifdef _WIN32// Fix strings in tzname[] to avoid long names with non-ascii characters.// If TZ is not set, tzset() in the MSVC runtime sets tzname[] to the// national language timezone names returned by GetTimezoneInformation().static char * fixtzname(char * dest, int destsize, const char * src){  int i = 0, j = 0;  while (src[i] && j < destsize-1) {    int i2 = (const char *)_mbsinc((const unsigned char *)src+i) - src;    if (i2 > i+1)      i = i2; // Ignore multibyte chars    else {      if ('A' <= src[i] && src[i] <= 'Z')        dest[j++] = src[i]; // "Pacific Standard Time" => "PST"      i++;    }  }  if (j < 2)    j = 0;  dest[j] = 0;  return dest;}#endif // _WIN32// 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){  if (type<0x10)    return packet_types[type];    if (type<0x20)    return "Reserved";    return "Unknown";}// Returns 1 if machine is big endian, else zero.  This is a run-time// rather than a compile-time function.  We could do it at// compile-time but in principle there are architectures that can run// with either byte-ordering.int isbigendian(){  short i=0x0100;  char *tmp=(char *)&i;  return *tmp;}// Utility function prints date and time and timezone into a character// buffer of length>=64.  All the fuss is needed to get the right// timezone info (sigh).void dateandtimezoneepoch(char *buffer, time_t tval){  struct tm *tmval;  char *timezonename;  char datebuffer[DATEANDEPOCHLEN];  int lenm1;#ifdef _WIN32  char tzfixbuf[6+1];#endif  FixGlibcTimeZoneBug();    // Get the time structure.  We need this to determine if we are in  // daylight savings time or not.  tmval=localtime(&tval);    // Convert to an ASCII string, put in datebuffer  // same as: asctime_r(tmval, datebuffer);  strncpy(datebuffer, asctime(tmval), DATEANDEPOCHLEN);  datebuffer[DATEANDEPOCHLEN-1]='\0';    // Remove newline  lenm1=strlen(datebuffer)-1;  datebuffer[lenm1>=0?lenm1:0]='\0';    // correct timezone name  if (tmval->tm_isdst==0)    // standard time zone    timezonename=tzname[0];  else if (tmval->tm_isdst>0)    // daylight savings in effect    timezonename=tzname[1];  else    // unable to determine if daylight savings in effect    timezonename="";#ifdef _WIN32  // Fix long non-ascii timezone names  if (!getenv("TZ"))    timezonename=fixtzname(tzfixbuf, sizeof(tzfixbuf), timezonename);#endif    // Finally put the information into the buffer as needed.  snprintf(buffer, DATEANDEPOCHLEN, "%s %s", datebuffer, timezonename);    return;}// Date and timezone gets printed into string pointed to by buffervoid dateandtimezone(char *buffer){    // Get the epoch (time in seconds since Jan 1 1970)  time_t tval=time(NULL);    dateandtimezoneepoch(buffer, tval);  return;}// These are two utility functions for printing CVS IDs. Massagecvs()// returns distance that it has moved ahead in the input stringint massagecvs(char *out, const char *cvsid){  char *copy,*filename,*date,*version;  int retVal=0;  const char delimiters[] = " ,$";  // make a copy on the heap, go to first token,  if (!(copy=strdup(cvsid)))    return 0;  if (!(filename=strtok(copy, delimiters)))    goto endmassage;  // move to first instance of "Id:"  while (strcmp(filename,"Id:"))    if (!(filename=strtok(NULL, delimiters)))      goto endmassage;    // get filename, skip "v", get version and date  if (!(  filename=strtok(NULL, delimiters)  ) ||      !(           strtok(NULL, delimiters)  ) ||      !(   version=strtok(NULL, delimiters)  ) ||      !(      date=strtok(NULL, delimiters)  ) )    goto endmassage;    sprintf(out,"%-16s revision: %-5s date: %-15s", filename, version, date);  retVal = (date-copy)+strlen(date);   endmassage:  free(copy);  return retVal;}// prints a single set of CVS idsvoid printone(char *block, const char *cvsid){  char strings[CVSMAXLEN];  const char *here=cvsid;  int bi=0, len=strlen(cvsid)+1;  // check that the size of the output block is sufficient  if (len>=CVSMAXLEN) {    pout("CVSMAXLEN=%d must be at least %d\n",CVSMAXLEN,len+1);    EXIT(1);  }  // loop through the different strings  while (bi<CVSMAXLEN && (len=massagecvs(strings,here))){    bi+=snprintf(block+bi,CVSMAXLEN-bi,"%s %s\n",(bi==0?"Module:":"  uses:"),strings);    here+=len;  }  return;}// A replacement for perror() that sends output to our choice of// printing. If errno not set then just print message.void syserror(const char *message){    if (errno) {    // Get the correct system error message:    const char *errormessage=strerror(errno);        // Check that caller has handed a sensible string, and provide    // appropriate output. See perrror(3) man page to understand better.    if (message && *message)      pout("%s: %s\n",message, errormessage);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -