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

📄 smartd.cpp

📁 硬盘各项性能的测试,如温度容量版本健康度型号
💻 CPP
📖 第 1 页 / 共 5 页
字号:
	   "Use ID = 0 to turn off -C and/or -U Directives\n"           "Example: /dev/hda -a\n",            configfile);  return;}/* Returns a pointer to a static string containing a formatted list of the valid   arguments to the option opt or NULL on failure. */const char *GetValidArgList(char opt) {  switch (opt) {  case 'c':    return "<FILE_NAME>, -";  case 's':    return "valid_regular_expression";  case 'l':    return "daemon, local0, local1, local2, local3, local4, local5, local6, local7";  case 'q':    return "nodev, errors, nodevstartup, never, onecheck, showtests";  case 'r':    return "ioctl[,N], ataioctl[,N], scsiioctl[,N]";  case 'p':    return "<FILE_NAME>";  case 'i':    return "<INTEGER_SECONDS>";  default:    return NULL;  }}/* prints help information for command syntax */void Usage (void){  PrintOut(LOG_INFO,"Usage: smartd [options]\n\n");#ifdef HAVE_GETOPT_LONG  PrintOut(LOG_INFO,"  -c NAME|-, --configfile=NAME|-\n");  PrintOut(LOG_INFO,"        Read configuration file NAME or stdin [default is %s]\n\n", configfile);  PrintOut(LOG_INFO,"  -d, --debug\n");  PrintOut(LOG_INFO,"        Start smartd in debug mode\n\n");  PrintOut(LOG_INFO,"  -D, --showdirectives\n");  PrintOut(LOG_INFO,"        Print the configuration file Directives and exit\n\n");  PrintOut(LOG_INFO,"  -h, --help, --usage\n");  PrintOut(LOG_INFO,"        Display this help and exit\n\n");  PrintOut(LOG_INFO,"  -i N, --interval=N\n");  PrintOut(LOG_INFO,"        Set interval between disk checks to N seconds, where N >= 10\n\n");  PrintOut(LOG_INFO,"  -l local[0-7], --logfacility=local[0-7]\n");#ifndef _WIN32  PrintOut(LOG_INFO,"        Use syslog facility local0 - local7 or daemon [default]\n\n");#else  PrintOut(LOG_INFO,"        Log to \"./smartd.log\", stdout, stderr [default is event log]\n\n");#endif#ifndef _WIN32  PrintOut(LOG_INFO,"  -n, --no-fork\n");  PrintOut(LOG_INFO,"        Do not fork into background\n\n");#endif  // _WIN32  PrintOut(LOG_INFO,"  -p NAME, --pidfile=NAME\n");  PrintOut(LOG_INFO,"        Write PID file NAME\n\n");  PrintOut(LOG_INFO,"  -q WHEN, --quit=WHEN\n");  PrintOut(LOG_INFO,"        Quit on one of: %s\n\n", GetValidArgList('q'));  PrintOut(LOG_INFO,"  -r, --report=TYPE\n");  PrintOut(LOG_INFO,"        Report transactions for one of: %s\n\n", GetValidArgList('r'));#ifdef _WIN32  PrintOut(LOG_INFO,"  --service\n");  PrintOut(LOG_INFO,"        Running as windows service (see man page), install with:\n");  PrintOut(LOG_INFO,"          smartd install [options]\n");  PrintOut(LOG_INFO,"        Remove service with:\n");  PrintOut(LOG_INFO,"          smartd remove\n\n");#else#endif // _WIN32 || __CYGWIN__  PrintOut(LOG_INFO,"  -V, --version, --license, --copyright\n");  PrintOut(LOG_INFO,"        Print License, Copyright, and version information\n");#else  PrintOut(LOG_INFO,"  -c NAME|-  Read configuration file NAME or stdin [default is %s]\n", configfile);  PrintOut(LOG_INFO,"  -d         Start smartd in debug mode\n");  PrintOut(LOG_INFO,"  -D         Print the configuration file Directives and exit\n");  PrintOut(LOG_INFO,"  -h         Display this help and exit\n");  PrintOut(LOG_INFO,"  -i N       Set interval between disk checks to N seconds, where N >= 10\n");  PrintOut(LOG_INFO,"  -l local?  Use syslog facility local0 - local7, or daemon\n");  PrintOut(LOG_INFO,"  -n         Do not fork into background\n");  PrintOut(LOG_INFO,"  -p NAME    Write PID file NAME\n");  PrintOut(LOG_INFO,"  -q WHEN    Quit on one of: %s\n", GetValidArgList('q'));  PrintOut(LOG_INFO,"  -r TYPE    Report transactions for one of: %s\n", GetValidArgList('r'));  PrintOut(LOG_INFO,"  -V         Print License, Copyright, and version information\n");#endif}// returns negative if problem, else fd>=0static int OpenDevice(char *device, char *mode, int scanning) {  int fd;  char *s=device;    // If there is an ASCII "space" character in the device name,  // terminate string there.  This is for 3ware and highpoint devices only.  if ((s=strchr(device,' ')))    *s='\0';  // open the device  fd = deviceopen(device, mode);  // if we removed a space, put it back in please  if (s)    *s=' ';  // if we failed to open the device, complain!  if (fd < 0) {    // For linux+devfs, a nonexistent device gives a strange error    // message.  This makes the error message a bit more sensible.    // If no debug and scanning - don't print errors    if (debugmode || !scanning) {      if (errno==ENOENT || errno==ENOTDIR)        errno=ENODEV;      PrintOut(LOG_INFO,"Device: %s, %s, open() failed\n",	       device, strerror(errno));    }    return -1;  }  // device opened sucessfully  return fd;}int CloseDevice(int fd, char *name){  if (deviceclose(fd)){    PrintOut(LOG_INFO,"Device: %s, %s, close(%d) failed\n", name, strerror(errno), fd);    return 1;  }  // device sucessfully closed  return 0;}// returns <0 on failureint ATAErrorCount(int fd, char *name){  struct ata_smart_errorlog log;    if (-1==ataReadErrorLog(fd,&log)){    PrintOut(LOG_INFO,"Device: %s, Read SMART Error Log Failed\n",name);    return -1;  }    // return current number of ATA errors  return log.error_log_pointer?log.ata_error_count:0;}// returns <0 if problem.  Otherwise, bottom 8 bits are the self test// error count, and top bits are the power-on hours of the last error.int SelfTestErrorCount(int fd, char *name){  struct ata_smart_selftestlog log;  if (-1==ataReadSelfTestLog(fd,&log)){    PrintOut(LOG_INFO,"Device: %s, Read SMART Self Test Log Failed\n",name);    return -1;  }    // return current number of self-test errors  return ataPrintSmartSelfTestlog(&log,0);}// scan to see what ata devices there are, and if they support SMARTint ATADeviceScan(cfgfile *cfg, int scanning){  int fd, supported=0;  struct ata_identify_device drive;  char *name=cfg->name;  int retainsmartdata=0;  int retid;  char *mode;    // should we try to register this as an ATA device?  switch (cfg->controller_type) {  case CONTROLLER_ATA:  case CONTROLLER_3WARE_678K:  case CONTROLLER_MARVELL_SATA:  case CONTROLLER_HPT:  case CONTROLLER_UNKNOWN:    mode="ATA";    break;  case CONTROLLER_3WARE_678K_CHAR:    mode="ATA_3WARE_678K";    break;  case CONTROLLER_3WARE_9000_CHAR:    mode="ATA_3WARE_9000";    break;  case CONTROLLER_SAT:    mode="SCSI";    break;  default:    // not a recognized ATA or SATA device.  We should never enter    // this branch.    return 1;  }    // open the device  if ((fd=OpenDevice(name, mode, scanning))<0)    // device open failed    return 1;  PrintOut(LOG_INFO,"Device: %s, opened\n", name);    // pass user settings on to low-level ATA commands  con->controller_port=cfg->controller_port;  con->hpt_data[0]=cfg->hpt_data[0];  con->hpt_data[1]=cfg->hpt_data[1];  con->hpt_data[2]=cfg->hpt_data[2];  con->controller_type=cfg->controller_type;  con->controller_explicit=cfg->controller_explicit;  con->fixfirmwarebug = cfg->fixfirmwarebug;  con->satpassthrulen = cfg->satpassthrulen;    // Get drive identity structure  if ((retid=ataReadHDIdentity (fd,&drive))){    if (retid<0)      // Unable to read Identity structure      PrintOut(LOG_INFO,"Device: %s, not ATA, no IDENTIFY DEVICE Structure\n",name);    else      PrintOut(LOG_INFO,"Device: %s, packet devices [this device %s] not SMART capable\n",               name, packetdevicetype(retid-1));    CloseDevice(fd, name);    return 2;   }  // Show if device in database, and use preset vendor attribute  // options unless user has requested otherwise.  if (cfg->ignorepresets)    PrintOut(LOG_INFO, "Device: %s, smartd database not searched (Directive: -P ignore).\n", name);  else {    // do whatever applypresets decides to do. Will allocate memory if    // cfg->attributedefs is needed.    if (applypresets(&drive, &cfg->attributedefs, con)<0)      PrintOut(LOG_INFO, "Device: %s, not found in smartd database.\n", name);    else      PrintOut(LOG_INFO, "Device: %s, found in smartd database.\n", name);        // then save the correct state of the flag (applypresets may have changed it)    cfg->fixfirmwarebug = con->fixfirmwarebug;  }    // If requested, show which presets would be used for this drive  if (cfg->showpresets) {    int savedebugmode=debugmode;    PrintOut(LOG_INFO, "Device %s: presets are:\n", name);    if (!debugmode)      debugmode=2;    showpresets(&drive);    debugmode=savedebugmode;  }  // see if drive supports SMART  supported=ataSmartSupport(&drive);  if (supported!=1) {    if (supported==0)      // drive does NOT support SMART      PrintOut(LOG_INFO,"Device: %s, lacks SMART capability\n",name);    else      // can't tell if drive supports SMART      PrintOut(LOG_INFO,"Device: %s, ATA IDENTIFY DEVICE words 82-83 don't specify if SMART capable.\n",name);      // should we proceed anyway?    if (cfg->permissive){      PrintOut(LOG_INFO,"Device: %s, proceeding since '-T permissive' Directive given.\n",name);    }    else {      PrintOut(LOG_INFO,"Device: %s, to proceed anyway, use '-T permissive' Directive.\n",name);      CloseDevice(fd, name);      return 2;    }  }    if (ataEnableSmart(fd)){    // Enable SMART command has failed    PrintOut(LOG_INFO,"Device: %s, could not enable SMART capability\n",name);    CloseDevice(fd, name);    return 2;   }    // disable device attribute autosave...  if (cfg->autosave==1){    if (ataDisableAutoSave(fd))      PrintOut(LOG_INFO,"Device: %s, could not disable SMART Attribute Autosave.\n",name);    else      PrintOut(LOG_INFO,"Device: %s, disabled SMART Attribute Autosave.\n",name);  }  // or enable device attribute autosave  if (cfg->autosave==2){    if (ataEnableAutoSave(fd))      PrintOut(LOG_INFO,"Device: %s, could not enable SMART Attribute Autosave.\n",name);    else      PrintOut(LOG_INFO,"Device: %s, enabled SMART Attribute Autosave.\n",name);  }  // capability check: SMART status  if (cfg->smartcheck && ataSmartStatus2(fd)==-1){    PrintOut(LOG_INFO,"Device: %s, not capable of SMART Health Status check\n",name);    cfg->smartcheck=0;  }    // capability check: Read smart values and thresholds.  Note that  // smart values are ALSO needed even if we ONLY want to know if the  // device is self-test log or error-log capable!  After ATA-5, this  // information was ALSO reproduced in the IDENTIFY DEVICE response,  // but sadly not for ATA-5.  Sigh.  // do we need to retain SMART data after returning from this routine?  retainsmartdata=cfg->usagefailed || cfg->prefail || cfg->usage || cfg->tempdiff || cfg->tempinfo || cfg->tempcrit;    // do we need to get SMART data?  if (retainsmartdata || cfg->autoofflinetest || cfg->selftest || cfg->errorlog || cfg->pending!=DONT_MONITOR_UNC) {    unsigned char currentpending, offlinepending;    cfg->smartval=(struct ata_smart_values *)Calloc(1,sizeof(struct ata_smart_values));    cfg->smartthres=(struct ata_smart_thresholds_pvt *)Calloc(1,sizeof(struct ata_smart_thresholds_pvt));        if (!cfg->smartval || !cfg->smartthres){      PrintOut(LOG_CRIT,"Not enough memory to obtain SMART data\n");      EXIT(EXIT_NOMEM);    }        if (ataReadSmartValues(fd,cfg->smartval) ||        ataReadSmartThresholds (fd,cfg->smartthres)){      PrintOut(LOG_INFO,"Device: %s, Read SMART Values and/or Thresholds Failed\n",name);      retainsmartdata=cfg->usagefailed=cfg->prefail=cfg->usage=0;      cfg->tempdiff = cfg->tempinfo = cfg->tempcrit = 0;      cfg->pending=DONT_MONITOR_UNC;    }        // see if the necessary Attribute is there to monitor offline or    // current pending sectors or temperature    TranslatePending(cfg->pending, &currentpending, &offlinepending);        if (currentpending && ATAReturnAttributeRawValue(currentpending, cfg->smartval)<0) {      PrintOut(LOG_INFO,"Device: %s, can't monitor Current Pending Sector count - no Attribute %d\n",	       name, (int)currentpending);      cfg->pending &= 0xff00;      cfg->pending |= CUR_UNC_DEFAULT;    }        if (offlinepending && ATAReturnAttributeRawValue(offlinepending, cfg->smartval)<0) {      PrintOut(LOG_INFO,"Device: %s, can't monitor Offline Uncorrectable Sector count  - no Attribute %d\n",	       name, (int)offlinepending);      cfg->pending &= 0x00ff;      cfg->pending |= OFF_UNC_DEFAULT<<8;    }    if (   (cfg->tempdiff || cfg->tempinfo || cfg->tempcrit)        && !ATAReturnTemperatureValue(cfg->smartval, cfg->attributedefs)) {      PrintOut(LOG_CRIT, "Device: %s, can't monitor Temperature, ignoring -W Directive\n", name);      cfg->tempdiff = cfg->tempinfo = cfg->tempcrit = 0;    }  }    // enable/disable automatic on-line testing  if (cfg->autoofflinetest){    // is this an enable or disable request?    const char *what=(cfg->autoofflinetest==1)?"disable":"enable";    if (!cfg->smartval)      PrintOut(LOG_INFO,"Device: %s, could not %s SMART Automatic Offline Testing.\n",name, what);    else {      // if command appears unsupported, issue a warning...      if (!isSupportAutomaticTimer(cfg->smartval))        PrintOut(LOG_INFO,"Device: %s, SMART Automatic Offline Testing unsupported...\n",name);      // ... but then try anyway      if ((cfg->autoofflinetest==1)?ataDisableAutoOffline(fd):ataEnableAutoOffline(fd))        PrintOut(LOG_INFO,"Device: %s, %s SMART Automatic Offline Testing failed.\n", name, what);      else        PrintOut(LOG_INFO,"Device: %s, %sd SMART Automatic Offline Testing.\n", name, what);    }  }    // capability check: self-test-log  if (cfg->selftest){    int retval;        // start with service disabled, and re-enable it if all works OK    cfg->selftest=0;    cfg->selflogcount=0;    cfg->selfloghour=0;    if (!cfg->smartval)      PrintOut(LOG_INFO, "Device: %s, no SMART Self-Test log (SMART READ DATA failed); disabling -l selftest\n", name);    else if (!cfg->permissive && !isSmartTestLogCapable(cfg->smartval, &drive))      PrintOut(LOG_INFO, "Device: %s, appears to lack SMART Self-Test log; disabling -l selftest (override with -T permissive Directive)\n", name);    else if ((retval=SelfTestErrorCount(fd, name))<0)      PrintOut(LOG_INFO, "Device: %s, no SMART Self-Test log; remove -l selftest Directive from smartd.conf\n", name);    else {      cfg->selftest=1;      cfg->selflogcount=SELFTEST_ERRORCOUNT(retval);      cfg->selfloghour =SELFTEST_ERRORHOURS(retval);    }  }

⌨️ 快捷键说明

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