13#define __STDC_FORMAT_MACROS 1  
   46#include "os_win32/popen.h"  
   48#pragma warning(disable:4761)  
   49typedef unsigned short mode_t;
 
   65#include <systemd/sd-daemon.h> 
   83#include "os_win32/daemon_win32.h"  
   84#define strsignal daemon_strsignal 
   85#define sleep     daemon_sleep 
   87#define SIGQUIT SIGBREAK 
   88#define SIGQUIT_KEYNAME "CONTROL-Break" 
   90#define SIGQUIT_KEYNAME "CONTROL-\\" 
  104  daemon_signal(sig, handler);
 
  109  sa.sa_handler = SIG_DFL;
 
  110  sigaction(sig, (
struct sigaction *)0, &sa);
 
  111  if (sa.sa_handler == SIG_IGN)
 
  115  sa.sa_handler = handler;
 
  116  sa.sa_flags = SA_RESTART; 
 
  117  sigaction(sig, &sa, (
struct sigaction *)0);
 
  127#define EXIT_BADCONF   2    
  128#define EXIT_STARTUP   3    
  131#define EXIT_READCONF  6    
  134#define EXIT_BADCODE   10   
  136#define EXIT_BADDEV    16   
  139#define EXIT_SIGNAL    254  
  155#ifdef SMARTMONTOOLS_SAVESTATES 
  156          = SMARTMONTOOLS_SAVESTATES
 
  162#ifdef SMARTMONTOOLS_ATTRIBUTELOG 
  163          = SMARTMONTOOLS_ATTRIBUTELOG
 
  179static bool warn_as_user;
 
  180static uid_t warn_uid;
 
  181static gid_t warn_gid;
 
  182static std::string warn_uname, warn_gname;
 
  185static bool warn_as_restr_user;
 
  212static volatile int caughtsigUSR2=0;
 
  223static void PrintOut(
int priority, 
const char *
fmt, ...)
 
  226#ifdef HAVE_LIBSYSTEMD 
  229static bool notify_enabled = 
false;
 
  230static bool notify_ready = 
false;
 
  234  if (!getenv(
"NOTIFY_SOCKET"))
 
  236  notify_enabled = 
true;
 
  244    PrintOut(LOG_CRIT, 
"Option -n (--no-fork) is required if 'Type=notify' is set.\n");
 
  256  const char * notify = 
"EXTEND_TIMEOUT_USEC=20000000"; 
 
  258    pout(
"sd_notify(0, \"%s\")\n", notify);
 
  261  sd_notify(0, notify);
 
  264static void notify_msg(
const char * msg, 
bool ready = 
false)
 
  269    pout(
"sd_notify(0, \"%sSTATUS=%s\")\n", (ready ? 
"READY=1\\n" : 
""), msg);
 
  272  sd_notifyf(0, 
"%sSTATUS=%s", (ready ? 
"READY=1\n" : 
""), msg);
 
  280  snprintf(msg, 
sizeof(msg), 
"Checking %d device%s ...",
 
  281           numdev, (numdev != 1 ? 
"s" : 
""));
 
  285static void notify_wait(time_t wakeuptime, 
int numdev)
 
  289  char ts[16] = 
""; 
struct tm tmbuf;
 
  292  snprintf(msg, 
sizeof(msg), 
"Next check of %d device%s will start at %s",
 
  293           numdev, (numdev != 1 ? 
"s" : 
""), ts);
 
  304    case 0:             msg = 
"Exiting ..."; 
break;
 
  305    case EXIT_BADCMD:   msg = 
"Error in command line (see SYSLOG)"; 
break;
 
  307    case EXIT_READCONF: msg = 
"Error in config file (see SYSLOG)"; 
break;
 
  308    case EXIT_BADDEV:   msg = 
"Unable to register a device (see SYSLOG)"; 
break;
 
  309    case EXIT_NODEV:    msg = 
"No devices to monitor"; 
break;
 
  310    default:            msg = 
"Error (see SYSLOG)"; 
break;
 
  323  if (getenv(
"NOTIFY_SOCKET")) {
 
  324    PrintOut(LOG_CRIT, 
"This version of smartd was build without 'Type=notify' support.\n");
 
  360  bool is_set(
int id, 
unsigned char flag)
 const 
  361    { 
return (0 < 
id && 
id < (
int)
sizeof(
m_flags) && (
m_flags[
id] & flag)); }
 
  365      if (0 < 
id && 
id < (
int)
sizeof(
m_flags))
 
  594           | ((uint64_t)ta.
raw[3] << 24)
 
  595           | ((uint64_t)ta.
raw[4] << 32)
 
  596           | ((uint64_t)ta.
raw[5] << 40);
 
  610      memset(ta.
raw, 0, 
sizeof(ta.
raw));
 
  615    ta.
raw[0] = (
unsigned char) pa.
raw;
 
  616    ta.
raw[1] = (
unsigned char)(pa.
raw >>  8);
 
  617    ta.
raw[2] = (
unsigned char)(pa.
raw >> 16);
 
  618    ta.
raw[3] = (
unsigned char)(pa.
raw >> 24);
 
  619    ta.
raw[4] = (
unsigned char)(pa.
raw >> 32);
 
  620    ta.
raw[5] = (
unsigned char)(pa.
raw >> 40);
 
  647     "|(self-test-errors)"  
  648     "|(self-test-last-err-hour)"  
  649     "|(scheduled-test-next-check)"  
  650     "|(selective-test-last-start)"  
  651     "|(selective-test-last-end)"  
  653     "|(mail\\.([0-9]+)\\."  
  659     "|(ata-smart-attribute\\.([0-9]+)\\."  
  667     "|(nvme-err-log-entries)"  
  668     "|(nvme-available-spare)"  
  669     "|(nvme-percentage-used)"  
  670     "|(nvme-media-errors)"  
  672     " *= *([0-9]+)[ \n]*$"  
  675  constexpr int nmatch = 1+28;
 
  679  if (
match[nmatch-1].rm_so < 0)
 
  682  uint64_t val = strtoull(line + 
match[nmatch-1].rm_so, (
char **)0, 10);
 
  685  if (
match[++m].rm_so >= 0)
 
  686    state.
tempmin = (
unsigned char)val;
 
  687  else if (
match[++m].rm_so >= 0)
 
  688    state.
tempmax = (
unsigned char)val;
 
  689  else if (
match[++m].rm_so >= 0)
 
  691  else if (
match[++m].rm_so >= 0)
 
  693  else if (
match[++m].rm_so >= 0)
 
  695  else if (
match[++m].rm_so >= 0)
 
  697  else if (
match[++m].rm_so >= 0)
 
  699  else if (
match[++m].rm_so >= 0)
 
  701  else if (
match[m+=2].rm_so >= 0) {
 
  702    int i = atoi(line+
match[m].rm_so);
 
  707    if (
match[m+=2].rm_so >= 0)
 
  709    else if (
match[++m].rm_so >= 0)
 
  711    else if (
match[++m].rm_so >= 0)
 
  716  else if (
match[m+=5+1].rm_so >= 0) {
 
  717    int i = atoi(line+
match[m].rm_so);
 
  720    if (
match[m+=2].rm_so >= 0)
 
  722    else if (
match[++m].rm_so >= 0)
 
  724    else if (
match[++m].rm_so >= 0)
 
  726    else if (
match[++m].rm_so >= 0)
 
  728    else if (
match[++m].rm_so >= 0)
 
  733  else if (
match[m+=7].rm_so >= 0)
 
  735  else if (
match[++m].rm_so >= 0)
 
  737  else if (
match[++m].rm_so >= 0)
 
  739  else if (
match[++m].rm_so >= 0)
 
  752      pout(
"Cannot read state file \"%s\"\n", path);
 
  756  setmode(fileno(f), O_TEXT); 
 
  760  int good = 0, bad = 0;
 
  762  while (fgets(line, 
sizeof(line), f)) {
 
  763    const char * 
s = line + strspn(line, 
" \t");
 
  764    if (!*
s || *
s == 
'#')
 
  774      pout(
"%s: format error\n", path);
 
  777    pout(
"%s: %d invalid line(s) ignored\n", path, bad);
 
  788    fprintf(f, 
"%s = %" PRIu64 
"\n", name, val);
 
  794    fprintf(f, 
"%s.%d.%s = %" PRIu64 
"\n", name1, 
id, name2, val);
 
  801  std::string pathbak = path; pathbak += 
'~';
 
  802  unlink(pathbak.c_str());
 
  803  rename(path, pathbak.c_str());
 
  807    pout(
"Cannot create state file \"%s\"\n", path);
 
  811  fprintf(f, 
"# smartd state file\n");
 
  859    fprintf(f, 
"\t%d;%d;%" PRIu64 
";", pa.id, pa.val, pa.raw);
 
  866  const char * pageNames[3] = {
"read", 
"write", 
"verify"};
 
  867  for (
int k = 0; k < 3; ++k) {
 
  870     fprintf(f, 
"\t%s-corr-by-ecc-fast;%" PRIu64 
";" 
  871       "\t%s-corr-by-ecc-delayed;%" PRIu64 
";" 
  872       "\t%s-corr-by-retry;%" PRIu64 
";" 
  873       "\t%s-total-err-corrected;%" PRIu64 
";" 
  874       "\t%s-corr-algorithm-invocations;%" PRIu64 
";" 
  875       "\t%s-gb-processed;%.3f;" 
  876       "\t%s-total-unc-errors;%" PRIu64 
";",
 
  882       pageNames[k], (ecp->
counter[5] / 1000000000.0),
 
  883       pageNames[k], ecp->
counter[6]);
 
  890    fprintf(f, 
"\ttemperature;%d;", state.
temperature);
 
  898    "\tcritical-warning;%d;" 
  900    "\tavailable-spare;%d;" 
  901    "\tavailable-spare-threshold;%d;" 
  902    "\tpercentage-used;%d;" 
  903    "\tdata-units-read;%" PRIu64 
";" 
  904    "\tdata-units-written;%" PRIu64 
";" 
  905    "\thost-reads;%" PRIu64 
";" 
  906    "\thost-writes;%" PRIu64 
";" 
  907    "\tcontroller-busy-time;%" PRIu64 
";" 
  908    "\tpower-cycles;%" PRIu64 
";" 
  909    "\tpower-on-hours;%" PRIu64 
";" 
  910    "\tunsafe-shutdowns;%" PRIu64 
";" 
  911    "\tmedia-errors;%" PRIu64 
";" 
  912    "\tnum-err-log-entries;%" PRIu64 
";",
 
  936    pout(
"Cannot create attribute log file \"%s\"\n", path);
 
  940  time_t now = time(
nullptr);
 
  942  fprintf(f, 
"%d-%02d-%02d %02d:%02d:%02d;",
 
  943             1900+tms->tm_year, 1+tms->tm_mon, tms->tm_mday,
 
  944             tms->tm_hour, tms->tm_min, tms->tm_sec);
 
  960                                 bool write_always = 
true)
 
  962  for (
unsigned i = 0; i < states.size(); i++) {
 
  973      PrintOut(LOG_INFO, 
"Device: %s, state written to %s\n",
 
  982  for (
unsigned i = 0; i < states.size(); i++) {
 
  992      PrintOut(LOG_INFO, 
"Device: %s, attribute log written to %s\n",
 
 1009static void USR2handler(
int sig)
 
 1037#ifdef HAVE_LIBCAP_NG 
 1040static int capabilities_mode ; 
 
 1044  if (!capabilities_mode)
 
 1046  capng_clear(CAPNG_SELECT_BOTH);
 
 1047  capng_updatev(CAPNG_ADD, (capng_type_t)(CAPNG_EFFECTIVE|CAPNG_PERMITTED),
 
 1048    CAP_SYS_ADMIN, CAP_MKNOD, CAP_SYS_RAWIO, -1);
 
 1049  if (warn_as_user && (warn_uid || warn_gid)) {
 
 1051    capng_updatev(CAPNG_ADD, (capng_type_t)(CAPNG_EFFECTIVE|CAPNG_PERMITTED),
 
 1052      CAP_SETGID, CAP_SETUID, -1);
 
 1054  if (capabilities_mode > 1) {
 
 1056    capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET,
 
 1057      CAP_SETGID, CAP_SETUID, CAP_CHOWN, CAP_FOWNER, CAP_DAC_OVERRIDE, -1);
 
 1059  capng_apply(CAPNG_SELECT_BOTH);
 
 1064  if (!capabilities_mode)
 
 1066  PrintOut(LOG_INFO, 
"If mail notification does not work with '--capabilities%s\n",
 
 1067           (capabilities_mode == 1 ? 
"', try '--capabilities=mail'" 
 1068                                   : 
"=mail', please inform " PACKAGE_BUGREPORT));
 
 1096  void set(
const char * name, 
const char * value);
 
 1103  int size = strlen(name) + 1 + strlen(value) + 1;
 
 1104  char * newbuf = 
new char[
size];
 
 1105  snprintf(newbuf, 
size, 
"%s=%s", name, value);
 
 1108    throw std::runtime_error(
"putenv() failed");
 
 1129  static const char * 
const whichfail[] = {
 
 1135    "FailedHealthCheck",          
 
 1136    "FailedReadSmartData",        
 
 1137    "FailedReadSmartErrorLog",    
 
 1138    "FailedReadSmartSelfTestLog", 
 
 1140    "CurrentPendingSector",       
 
 1141    "OfflineUncorrectableSector", 
 
 1147    PrintOut(LOG_CRIT, 
"Internal error in MailWarning(): which=%d\n", which);
 
 1155    days = nextdays = -1; 
 
 1158      days = nextdays = -1; 
break;
 
 1160      days = nextdays = 0; 
break;
 
 1162      days = nextdays = 1; 
break;
 
 1165      nextdays = 1 << ((unsigned)mail->
logged <= 5 ? mail->
logged : 5);
 
 1167      days = ((unsigned)mail->
logged <= 5 ? nextdays >> 1 : nextdays);
 
 1170      PrintOut(LOG_CRIT, 
"Internal error in MailWarning(): cfg.emailfreq=%d\n", (
int)cfg.
emailfreq);
 
 1174  time_t now = time(
nullptr);
 
 1179    if (days > 0 && now < mail->lastsent + days * 24 * 3600)
 
 1203  std::replace(address.begin(), address.end(), 
',', 
' ');
 
 1209  env[0].
set(
"SMARTD_MAILER", executable);
 
 1210  env[1].
set(
"SMARTD_MESSAGE", message);
 
 1212  snprintf(dates, 
sizeof(dates), 
"%d", mail->
logged);
 
 1213  env[2].
set(
"SMARTD_PREVCNT", dates);
 
 1215  env[3].
set(
"SMARTD_TFIRST", dates);
 
 1217  env[4].
set(
"SMARTD_TFIRSTEPOCH", dates);
 
 1218  env[5].
set(
"SMARTD_FAILTYPE", whichfail[which]);
 
 1219  env[6].
set(
"SMARTD_ADDRESS", address.c_str());
 
 1220  env[7].
set(
"SMARTD_DEVICESTRING", cfg.
name.c_str());
 
 1223  env[8].
set(
"SMARTD_DEVICETYPE",
 
 1225  env[9].
set(
"SMARTD_DEVICE", cfg.
dev_name.c_str());
 
 1230    snprintf(dates, 
sizeof(dates), 
"%d", nextdays);
 
 1231  env[11].
set(
"SMARTD_NEXTDAYS", dates);
 
 1233  env[12].
set(
"SMARTD_SUBJECT", 
"");
 
 1237    executable = 
"<mail>";
 
 1238  const char * newadd = (!address.empty()? address.c_str() : 
"<nomailer>");
 
 1239  const char * newwarn = (which? 
"Warning via" : 
"Test of");
 
 1244  snprintf(command, 
sizeof(command), 
"\"%s\" 2>&1", 
warning_script.c_str());
 
 1246  snprintf(command, 
sizeof(command), 
"%s 2>&1", 
warning_script.c_str());
 
 1250  PrintOut(LOG_INFO,
"%s %s to %s%s ...\n",
 
 1251           (which ? 
"Sending warning via" : 
"Executing test of"), executable, newadd,
 
 1253#ifdef HAVE_POSIX_API
 
 1256                      (
unsigned)warn_uid, warn_uname.c_str(),
 
 1257                      (
unsigned)warn_gid, warn_gname.c_str() ).c_str() :
 
 1259            warn_as_restr_user ? 
" (restricted user)" :
 
 1269#ifdef HAVE_POSIX_API 
 1276    pfp = popen_as_restr_user(command, 
"r", warn_as_restr_user);
 
 1278    pfp = popen(command, 
"r");
 
 1284    PrintOut(LOG_CRIT,
"%s %s to %s: failed (fork or pipe failed, or no memory) %s\n", 
 
 1285             newwarn,  executable, newadd, errno?strerror(errno):
"");
 
 1296      PrintOut(LOG_CRIT,
"%s %s to %s produced unexpected output (%s%d bytes) to STDOUT/STDERR: \n%s\n", 
 
 1297               newwarn, executable, newadd, len!=newlen?
"here truncated to ":
"", newlen, 
buffer);
 
 1305        PrintOut(LOG_CRIT,
"%s %s to %s: flushed remaining STDOUT/STDERR\n",
 
 1306                 newwarn, executable, newadd);
 
 1308        PrintOut(LOG_CRIT,
"%s %s to %s: more than 1 MB STDOUT/STDERR flushed, breaking pipe\n",
 
 1309                 newwarn, executable, newadd);
 
 1316#ifdef HAVE_POSIX_API 
 1322      status = pclose(pfp);
 
 1326      PrintOut(LOG_CRIT,
"%s %s to %s: pclose(3) failed %s\n", newwarn, executable, newadd,
 
 1327               errno?strerror(errno):
"");
 
 1330      if (WIFEXITED(status)) {
 
 1332        int status8 = WEXITSTATUS(status);
 
 1334          PrintOut(LOG_CRIT,
"%s %s to %s: failed (32-bit/8-bit exit status: %d/%d) perhaps caught signal %d [%s]\n",
 
 1335                   newwarn, executable, newadd, status, status8, status8-128, strsignal(status8-128));
 
 1337          PrintOut(LOG_CRIT,
"%s %s to %s: failed (32-bit/8-bit exit status: %d/%d)\n",
 
 1338                   newwarn, executable, newadd, status, status8);
 
 1342          PrintOut(LOG_INFO,
"%s %s to %s: successful\n", newwarn, executable, newadd);
 
 1345      if (WIFSIGNALED(status))
 
 1346        PrintOut(LOG_INFO,
"%s %s to %s: exited because of uncaught signal %d [%s]\n",
 
 1347                 newwarn, executable, newadd, WTERMSIG(status), strsignal(WTERMSIG(status)));
 
 1351      if (WIFSTOPPED(status)) 
 
 1352        PrintOut(LOG_CRIT,
"%s %s to %s: process STOPPED because it caught signal %d [%s]\n",
 
 1353                 newwarn, executable, newadd, WSTOPSIG(status), strsignal(WSTOPSIG(status)));
 
 1382  PrintOut(LOG_INFO, 
"Device: %s, %s, warning condition reset after %d email%s\n", cfg.
name.c_str(),
 
 1394static 
void vsyslog_lines(
int priority, const 
char * 
fmt, va_list 
ap)
 
 1399  for (
char * p = buf, * q; p && *p; p = q) {
 
 1400    if ((q = strchr(p, 
'\n')))
 
 1403      syslog(priority, 
"%s\n", p);
 
 1409#define vsyslog_lines vsyslog 
 1433    vfprintf(f, 
fmt, 
ap);
 
 1438    openlog(
"smartd", LOG_PID, 
facility);
 
 1439    vsyslog_lines(LOG_INFO, 
fmt, 
ap);
 
 1460    vfprintf(f, 
fmt, 
ap);
 
 1464    openlog(
"smartd", LOG_PID, 
facility);
 
 1465    vsyslog_lines(priority, 
fmt, 
ap);
 
 1475  pout(
"Warning! %s error: invalid SMART checksum.\n", 
string);
 
 1484  int waited, max_wait = 10;
 
 1485  struct stat stat_buf;
 
 1490  for(waited = 0; waited < max_wait; ++waited) {
 
 1491    if (!stat(
pid_file.c_str(), &stat_buf)) {
 
 1515    if ((pid=fork()) < 0) {
 
 1517      PrintOut(LOG_CRIT,
"smartd unable to fork daemon process!\n");
 
 1533    if ((pid=fork()) < 0) {
 
 1535      PrintOut(LOG_CRIT,
"smartd unable to fork daemon process!\n");
 
 1546  int open_max = sysconf(_SC_OPEN_MAX);
 
 1547#ifdef HAVE_CLOSE_RANGE 
 1548  if (close_range(0, open_max - 1, 0))
 
 1553    for (
int i = 0, failed = 0; i < open_max && failed < 1024; i++)
 
 1554      failed = (!close(i) ? 0 : failed + 1);
 
 1558  int fd = open(
"/dev/null", O_RDWR);
 
 1559  if (!(fd == 0 && dup(fd) == 1 && dup(fd) == 2 && !chdir(
"/"))) {
 
 1560    PrintOut(LOG_CRIT, 
"smartd unable to redirect to /dev/null or to chdir to root!\n");
 
 1566    PrintOut(LOG_INFO, 
"smartd has fork()ed into background mode. New PID=%d.\n", (
int)getpid());
 
 1573  if (daemon_detach(
"smartd")) {
 
 1574    PrintOut(LOG_CRIT,
"smartd unable to detach from console!\n");
 
 1589    pid_t pid = getpid();
 
 1592    old_umask = umask(0077); 
 
 1595    old_umask = umask(0033); 
 
 1600    if (!(f && fprintf(f, 
"%d\n", (
int)pid) > 0 && f.
close())) {
 
 1601      PrintOut(LOG_CRIT, 
"unable to write PID file %s - exiting.\n", 
pid_file.c_str());
 
 1604    PrintOut(LOG_INFO, 
"file %s written containing PID %d\n", 
pid_file.c_str(), (
int)pid);
 
 1619           "Configuration file (%s) Directives (after device name):\n" 
 1620           "  -d TYPE Set the device type: auto, ignore, removable,\n" 
 1622           "  -T TYPE Set the tolerance to one of: normal, permissive\n" 
 1623           "  -o VAL  Enable/disable automatic offline tests (on/off)\n" 
 1624           "  -S VAL  Enable/disable attribute autosave (on/off)\n" 
 1625           "  -n MODE No check if: never, sleep[,N][,q], standby[,N][,q], idle[,N][,q]\n" 
 1626           "  -H      Monitor SMART Health Status, report if failed\n" 
 1627           "  -H MASK Monitor specific NVMe Critical Warning bits\n" 
 1628           "  -s REG  Do Self-Test at time(s) given by regular expression REG\n" 
 1629           "  -l TYPE Monitor SMART log or self-test status:\n" 
 1630           "          error, selftest, xerror, offlinests[,ns], selfteststs[,ns]\n" 
 1631           "  -l scterc,R,W  Set SCT Error Recovery Control\n" 
 1632           "  -e      Change device setting: aam,[N|off], apm,[N|off], dsn,[on|off],\n" 
 1633           "          lookahead,[on|off], security-freeze, standby,[N|off], wcache,[on|off]\n" 
 1634           "  -f      Monitor 'Usage' Attributes, report failures\n" 
 1635           "  -m ADD  Send email warning to address ADD\n" 
 1636           "  -M TYPE Modify email warning behavior (see man page)\n" 
 1637           "  -p      Report changes in 'Prefailure' Attributes\n" 
 1638           "  -u      Report changes in 'Usage' Attributes\n" 
 1639           "  -t      Equivalent to -p and -u Directives\n" 
 1640           "  -r ID   Also report Raw values of Attribute ID with -p, -u or -t\n" 
 1641           "  -R ID   Track changes in Attribute ID Raw value with -p, -u or -t\n" 
 1642           "  -i ID   Ignore Attribute ID for -f Directive\n" 
 1643           "  -I ID   Ignore Attribute ID for -p, -u or -t Directive\n" 
 1644           "  -C ID[+] Monitor [increases of] Current Pending Sectors in Attribute ID\n" 
 1645           "  -U ID[+] Monitor [increases of] Offline Uncorrectable Sectors in Attribute ID\n" 
 1646           "  -W D,I,C Monitor Temperature D)ifference, I)nformal limit, C)ritical limit\n" 
 1647           "  -v N,ST Modifies labeling of Attribute N (see man page)  \n" 
 1648           "  -P TYPE Drive-specific presets: use, ignore, show, showall\n" 
 1649           "  -a      Default: -H -f -t -l error -l selftest -l selfteststs -C 197 -U 198\n" 
 1650           "  -F TYPE Use firmware bug workaround:\n" 
 1652           "  -c i=N  Set interval between disk checks to N seconds\n" 
 1653           "   #      Comment: text after a hash sign is ignored\n" 
 1654           "   \\      Line continuation character\n" 
 1655           "Attribute ID is a decimal integer 1 <= ID <= 255\n" 
 1656           "Use ID = 0 to turn off -C and/or -U Directives\n" 
 1657           "Example: /dev/sda -a\n",
 
 1659           smi()->get_valid_dev_types_str().c_str(),
 
 1670    return "<PATH_PREFIX>, -";
 
 1672    return "[+]<FILE_NAME>";
 
 1674    return "<FILE_NAME>, -";
 
 1676    return "daemon, local0, local1, local2, local3, local4, local5, local6, local7";
 
 1678    return "nodev[0], errors[,nodev0], nodev[0]startup, never, onecheck, showtests";
 
 1680    return "ioctl[,N], ataioctl[,N], scsiioctl[,N], nvmeioctl[,N]";
 
 1683    return "<FILE_NAME>";
 
 1685    return "<INTEGER_SECONDS>";
 
 1686#ifdef HAVE_POSIX_API 
 1688    return "<USER>[:<GROUP>], -";
 
 1689#elif defined(_WIN32) 
 1691    return "restricted, unchanged";
 
 1693#ifdef HAVE_LIBCAP_NG 
 1695    return "mail, <no_argument>";
 
 1705  PrintOut(LOG_INFO,
"Usage: smartd [options]\n\n");
 
 1706#ifdef SMARTMONTOOLS_ATTRIBUTELOG 
 1707  PrintOut(LOG_INFO,
"  -A PREFIX|-, --attributelog=PREFIX|-\n");
 
 1709  PrintOut(LOG_INFO,
"  -A PREFIX, --attributelog=PREFIX\n");
 
 1711  PrintOut(LOG_INFO,
"        Log attribute information to {PREFIX}MODEL-SERIAL.TYPE.csv\n");
 
 1712#ifdef SMARTMONTOOLS_ATTRIBUTELOG 
 1713  PrintOut(LOG_INFO,
"        [default is " SMARTMONTOOLS_ATTRIBUTELOG 
"MODEL-SERIAL.TYPE.csv]\n");
 
 1716  PrintOut(LOG_INFO,
"  -B [+]FILE, --drivedb=[+]FILE\n");
 
 1717  PrintOut(LOG_INFO,
"        Read and replace [add] drive database from FILE\n");
 
 1719#ifdef SMARTMONTOOLS_DRIVEDBDIR 
 1721  PrintOut(LOG_INFO,
"         and then    %s", get_drivedb_path_default());
 
 1724  PrintOut(LOG_INFO,
"  -c NAME|-, --configfile=NAME|-\n");
 
 1725  PrintOut(LOG_INFO,
"        Read configuration file NAME or stdin\n");
 
 1727#ifdef HAVE_LIBCAP_NG 
 1728  PrintOut(LOG_INFO,
"  -C, --capabilities[=mail]\n");
 
 1729  PrintOut(LOG_INFO,
"        Drop unneeded Linux process capabilities.\n" 
 1730                    "        Warning: Mail notification may not work when used.\n\n");
 
 1732  PrintOut(LOG_INFO,
"  -d, --debug\n");
 
 1733  PrintOut(LOG_INFO,
"        Start smartd in debug mode\n\n");
 
 1734  PrintOut(LOG_INFO,
"  -D, --showdirectives\n");
 
 1735  PrintOut(LOG_INFO,
"        Print the configuration file Directives and exit\n\n");
 
 1736  PrintOut(LOG_INFO,
"  -h, --help, --usage\n");
 
 1737  PrintOut(LOG_INFO,
"        Display this help and exit\n\n");
 
 1738  PrintOut(LOG_INFO,
"  -i N, --interval=N\n");
 
 1739  PrintOut(LOG_INFO,
"        Set interval between disk checks to N seconds, where N >= 10\n\n");
 
 1740  PrintOut(LOG_INFO,
"  -l local[0-7], --logfacility=local[0-7]\n");
 
 1742  PrintOut(LOG_INFO,
"        Use syslog facility local0 - local7 or daemon [default]\n\n");
 
 1744  PrintOut(LOG_INFO,
"        Log to \"./smartd.log\", stdout, stderr [default is event log]\n\n");
 
 1747  PrintOut(LOG_INFO,
"  -n, --no-fork\n");
 
 1748  PrintOut(LOG_INFO,
"        Do not fork into background\n");
 
 1749#ifdef HAVE_LIBSYSTEMD 
 1750  PrintOut(LOG_INFO,
"        (systemd 'Type=notify' is assumed if $NOTIFY_SOCKET is set)\n");
 
 1754  PrintOut(LOG_INFO,
"  -p NAME, --pidfile=NAME\n");
 
 1755  PrintOut(LOG_INFO,
"        Write PID file NAME\n\n");
 
 1756  PrintOut(LOG_INFO,
"  -q WHEN, --quit=WHEN\n");
 
 1758  PrintOut(LOG_INFO,
"  -r, --report=TYPE\n");
 
 1760#ifdef SMARTMONTOOLS_SAVESTATES 
 1761  PrintOut(LOG_INFO,
"  -s PREFIX|-, --savestates=PREFIX|-\n");
 
 1763  PrintOut(LOG_INFO,
"  -s PREFIX, --savestates=PREFIX\n");
 
 1765  PrintOut(LOG_INFO,
"        Save disk states to {PREFIX}MODEL-SERIAL.TYPE.state\n");
 
 1766#ifdef SMARTMONTOOLS_SAVESTATES 
 1767  PrintOut(LOG_INFO,
"        [default is " SMARTMONTOOLS_SAVESTATES 
"MODEL-SERIAL.TYPE.state]\n");
 
 1770  PrintOut(LOG_INFO,
"  -w NAME, --warnexec=NAME\n");
 
 1771  PrintOut(LOG_INFO,
"        Run executable NAME on warnings\n");
 
 1773  PrintOut(LOG_INFO,
"        [default is " SMARTMONTOOLS_SMARTDSCRIPTDIR 
"/smartd_warning.sh]\n\n");
 
 1777#ifdef HAVE_POSIX_API 
 1778  PrintOut(LOG_INFO,
"  -u USER[:GROUP], --warn-as-user=USER[:GROUP]\n");
 
 1779  PrintOut(LOG_INFO,
"        Run warning script as non-privileged USER\n\n");
 
 1780#elif defined(_WIN32) 
 1781  PrintOut(LOG_INFO,
"  -u MODE, --warn-as-user=MODE\n");
 
 1786  PrintOut(LOG_INFO,
"        Running as windows service (see man page), install with:\n");
 
 1787  PrintOut(LOG_INFO,
"          smartd install [options]\n");
 
 1788  PrintOut(LOG_INFO,
"        Remove service with:\n");
 
 1789  PrintOut(LOG_INFO,
"          smartd remove\n\n");
 
 1791  PrintOut(LOG_INFO,
"  -V, --version, --license, --copyright\n");
 
 1792  PrintOut(LOG_INFO,
"        Print License, Copyright, and version information\n");
 
 1797  if (!device->
close()){
 
 1808  bool changed = 
false;
 
 1809  for (
unsigned i = 0; i < 
s.size(); i++) {
 
 1813    if ((
' ' <= c && c <= 
'~') && !(i == 0 && c == 
'~'))
 
 1824  return !(   (
'0' <= c && c <= 
'9')
 
 1825           || (
'A' <= c && c <= 
'Z')
 
 1826           || (
'a' <= c && c <= 
'z'));
 
 1837      PrintOut(LOG_INFO,
"Device: %s, Read Summary SMART Error Log failed\n",name);
 
 1845      PrintOut(LOG_INFO,
"Device: %s, Read Extended Comprehensive SMART Error Log failed\n",name);
 
 1863    PrintOut(LOG_INFO,
"Device: %s, Read SMART Self Test Log Failed\n",name);
 
 1873  for (
int i = 20; i >= 0; i--) {
 
 1879    int status = 
entry.selfteststatus >> 4;
 
 1880    if (status == 0x0 && (
entry.selftestnumber & 0x7f) == 0x02)
 
 1884    if (0x3 <= status && status <= 0x8) {
 
 1889        hour = 
entry.timestamp;
 
 1899  return ((status & 0x7f) == 0x03);
 
 1905  return ((status >> 4) == 0xf);
 
 1912  switch (status & 0x7f) {
 
 1913    case 0x00: msg = 
"was never started"; 
break;
 
 1914    case 0x02: msg = 
"was completed without error"; 
break;
 
 1915    case 0x03: msg = 
"is in progress"; 
break;
 
 1916    case 0x04: msg = 
"was suspended by an interrupting command from host"; 
break;
 
 1917    case 0x05: msg = 
"was aborted by an interrupting command from host"; 
break;
 
 1918    case 0x06: msg = 
"was aborted by the device with a fatal error"; 
break;
 
 1919    default:   msg = 
nullptr;
 
 1923    PrintOut(((status & 0x7f) == 0x06 ? LOG_CRIT : LOG_INFO),
 
 1924             "Device: %s, offline data collection %s%s\n", name, msg,
 
 1925             ((status & 0x80) ? 
" (auto:on)" : 
""));
 
 1927    PrintOut(LOG_INFO, 
"Device: %s, unknown offline data collection status 0x%02x\n",
 
 1935  switch (status >> 4) {
 
 1936    case 0x0: msg = 
"completed without error"; 
break;
 
 1937    case 0x1: msg = 
"was aborted by the host"; 
break;
 
 1938    case 0x2: msg = 
"was interrupted by the host with a reset"; 
break;
 
 1939    case 0x3: msg = 
"could not complete due to a fatal or unknown error"; 
break;
 
 1940    case 0x4: msg = 
"completed with error (unknown test element)"; 
break;
 
 1941    case 0x5: msg = 
"completed with error (electrical test element)"; 
break;
 
 1942    case 0x6: msg = 
"completed with error (servo/seek test element)"; 
break;
 
 1943    case 0x7: msg = 
"completed with error (read test element)"; 
break;
 
 1944    case 0x8: msg = 
"completed with error (handling damage?)"; 
break;
 
 1945    default:  msg = 
nullptr;
 
 1949    PrintOut(((status >> 4) >= 0x4 ? LOG_CRIT : LOG_INFO),
 
 1950             "Device: %s, previous self-test %s\n", name, msg);
 
 1951  else if ((status >> 4) == 0xf)
 
 1952    PrintOut(LOG_INFO, 
"Device: %s, self-test in progress, %u0%% remaining\n",
 
 1953             name, status & 0x0f);
 
 1955    PrintOut(LOG_INFO, 
"Device: %s, unknown self-test status 0x%02x\n",
 
 1961                             unsigned char id, 
const char * msg)
 
 1966    PrintOut(LOG_INFO, 
"Device: %s, can't monitor %s count - no Attribute %d\n",
 
 1967             cfg.
name.c_str(), msg, 
id);
 
 1975    PrintOut(LOG_INFO, 
"Device: %s, ignoring %s count - bogus Attribute %d value %" PRIu64 
" (0x%" PRIx64 
")\n",
 
 1976             cfg.
name.c_str(), msg, 
id, rawval, rawval);
 
 2002                                  int set_option = 0, 
bool has_value = 
false)
 
 2009  else if (set_option < 0)
 
 2013  else if (set_option > 0)
 
 2023  for (
const auto & prev_cfg : prev_cfgs) {
 
 2024    if (!prev_cfg.id_is_unique)
 
 2029          || (!prev_cfg.dev_idinfo_bc.empty() && cfg.
dev_idinfo == prev_cfg.dev_idinfo_bc)))
 
 2032    PrintOut(LOG_INFO, 
"Device: %s, same identity as %s, ignored\n",
 
 2033             cfg.
dev_name.c_str(), prev_cfg.dev_name.c_str());
 
 2049  const char *name = cfg.
name.c_str();
 
 2058      PrintOut(LOG_INFO,
"Device: %s, not ATA, no IDENTIFY DEVICE Structure\n",name);
 
 2060      PrintOut(LOG_INFO,
"Device: %s, packet devices [this device %s] not SMART capable\n",
 
 2067  char model[40+1], serial[20+1], firmware[8+1];
 
 2077  char wwn[64]; wwn[0] = 0;
 
 2078  unsigned oui = 0; uint64_t unique_id = 0;
 
 2081    snprintf(wwn, 
sizeof(wwn), 
"WWN:%x-%06x-%09" PRIx64 
", ", naa, oui, unique_id);
 
 2102    PrintOut(LOG_INFO, 
"Device: %s, smartd database not searched (Directive: -P ignore).\n", name);
 
 2105    std::string dbversion;
 
 2109      PrintOut(LOG_INFO, 
"Device: %s, not found in smartd database%s%s.\n", name,
 
 2110        (!dbversion.empty() ? 
" " : 
""), (!dbversion.empty() ? dbversion.c_str() : 
""));
 
 2112      PrintOut(LOG_INFO, 
"Device: %s, found in smartd database%s%s%s%s\n",
 
 2113        name, (!dbversion.empty() ? 
" " : 
""), (!dbversion.empty() ? dbversion.c_str() : 
""),
 
 2122  bool locked = ((word128 & 0x0007) == 0x0007); 
 
 2124    PrintOut(LOG_INFO, 
"Device: %s, ATA Security is **LOCKED**\n", name);
 
 2136    PrintOut(LOG_INFO, 
"Device %s: presets are:\n", name);
 
 2148      PrintOut(LOG_INFO,
"Device: %s, lacks SMART capability\n",name);
 
 2151      PrintOut(LOG_INFO,
"Device: %s, ATA IDENTIFY DEVICE words 82-83 don't specify if SMART capable.\n",name);
 
 2155      PrintOut(LOG_INFO,
"Device: %s, proceeding since '-T permissive' Directive given.\n",name);
 
 2158      PrintOut(LOG_INFO,
"Device: %s, to proceed anyway, use '-T permissive' Directive.\n",name);
 
 2166    PrintOut(LOG_INFO,
"Device: %s, could not enable SMART capability\n",name);
 
 2170        PrintOut(LOG_INFO, 
"Device: %s, to proceed anyway, use '-T permissive' Directive.\n", name);
 
 2174      PrintOut(LOG_INFO, 
"Device: %s, proceeding since '-T permissive' Directive given.\n", name);
 
 2177      PrintOut(LOG_INFO, 
"Device: %s, proceeding since SMART is already enabled\n", name);
 
 2184      PrintOut(LOG_INFO,
"Device: %s, could not disable SMART Attribute Autosave.\n",name);
 
 2186      PrintOut(LOG_INFO,
"Device: %s, disabled SMART Attribute Autosave.\n",name);
 
 2192      PrintOut(LOG_INFO,
"Device: %s, could not enable SMART Attribute Autosave.\n",name);
 
 2194      PrintOut(LOG_INFO,
"Device: %s, enabled SMART Attribute Autosave.\n",name);
 
 2199    PrintOut(LOG_INFO,
"Device: %s, not capable of SMART Health Status check\n",name);
 
 2210  bool smart_val_ok = 
false;
 
 2219      PrintOut(LOG_INFO, 
"Device: %s, Read SMART Values failed\n", name);
 
 2225      smart_val_ok = 
true;
 
 2227        PrintOut(LOG_INFO, 
"Device: %s, Read SMART Thresholds failed%s\n",
 
 2228                 name, (cfg.
usagefailed ? 
", ignoring -f Directive" : 
""));
 
 2239              "Current_Pending_Sector"))
 
 2244              "Offline_Uncorrectable"))
 
 2249      PrintOut(LOG_INFO, 
"Device: %s, can't monitor Temperature, ignoring -W %d,%d,%d\n",
 
 2255    for (
int id = 1; 
id <= 255; 
id++) {
 
 2263          PrintOut(LOG_INFO,
"Device: %s, no Attribute %d, ignoring -%c %d%s\n", name, 
id, opt, 
id, excl);
 
 2266          if (!((prefail && cfg.
prefail) || (!prefail && cfg.
usage)))
 
 2267            PrintOut(LOG_INFO,
"Device: %s, not monitoring %s Attributes, ignoring -%c %d%s\n", name,
 
 2268                     (prefail ? 
"Prefailure" : 
"Usage"), opt, 
id, excl);
 
 2279      PrintOut(LOG_INFO,
"Device: %s, could not %s SMART Automatic Offline Testing.\n",name, what);
 
 2283        PrintOut(LOG_INFO,
"Device: %s, SMART Automatic Offline Testing unsupported...\n",name);
 
 2286        PrintOut(LOG_INFO,
"Device: %s, %s SMART Automatic Offline Testing failed.\n", name, what);
 
 2288        PrintOut(LOG_INFO,
"Device: %s, %sd SMART Automatic Offline Testing.\n", name, what);
 
 2294  bool smart_logdir_ok = 
false, gp_logdir_ok = 
false;
 
 2300        smart_logdir_ok = 
true;
 
 2305      gp_logdir_ok = 
true;
 
 2311    int errcnt = 0; 
unsigned hour = 0;
 
 2315      PrintOut(LOG_INFO, 
"Device: %s, no SMART Self-test Log, ignoring -l selftest (override with -T permissive)\n", name);
 
 2319      PrintOut(LOG_INFO, 
"Device: %s, no SMART Self-test Log, ignoring -l selftest\n", name);
 
 2335      PrintOut(LOG_INFO, 
"Device: %s, no SMART Error Log, ignoring -l error (override with -T permissive)\n", name);
 
 2339      PrintOut(LOG_INFO, 
"Device: %s, no SMART Error Log, ignoring -l error\n", name);
 
 2350      PrintOut(LOG_INFO, 
"Device: %s, no Extended Comprehensive SMART Error Log, ignoring -l xerror (override with -T permissive)\n",
 
 2355      PrintOut(LOG_INFO, 
"Device: %s, no Extended Comprehensive SMART Error Log, ignoring -l xerror\n", name);
 
 2359      PrintOut(LOG_INFO, 
"Device: %s, SMART Error Logs report different error counts: %d != %d\n",
 
 2373        PrintOut(LOG_INFO, 
"Device: %s, no SMART Offline Data Collection capability, ignoring -l offlinests (override with -T permissive)\n", name);
 
 2375        PrintOut(LOG_INFO, 
"Device: %s, no SMART Self-test capability, ignoring -l selfteststs (override with -T permissive)\n", name);
 
 2384    if (-1 == powermode) {
 
 2385      PrintOut(LOG_CRIT, 
"Device: %s, no ATA CHECK POWER STATUS support, ignoring -n Directive\n", name);
 
 2388    else if (powermode!=0x00 && powermode!=0x01
 
 2389        && powermode!=0x40 && powermode!=0x41
 
 2390        && powermode!=0x80 && powermode!=0x81 && powermode!=0x82 && powermode!=0x83
 
 2391        && powermode!=0xff) {
 
 2392      PrintOut(LOG_CRIT, 
"Device: %s, CHECK POWER STATUS returned %d, not ATA compliant, ignoring -n Directive\n",
 
 2434    PrintOut(LOG_INFO, 
"Device: %s, ATA settings applied: %s\n", name, msg.c_str());
 
 2439      PrintOut(LOG_INFO, 
"Device: %s, no SCT Error Recovery Control support, ignoring -l scterc\n",
 
 2442      PrintOut(LOG_INFO, 
"Device: %s, no SCT support if ATA Security is LOCKED, ignoring -l scterc\n",
 
 2446      PrintOut(LOG_INFO, 
"Device: %s, set of SCT Error Recovery Control failed\n", name);
 
 2448      PrintOut(LOG_INFO, 
"Device: %s, SCT Error Recovery Control set to: Read: %u, Write: %u\n",
 
 2463  PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n",name);
 
 2476        PrintOut(LOG_INFO, 
"Device: %s, state read from %s\n", name, cfg.
state_file.c_str());
 
 2495  int err, req_len, avail_len, version, len;
 
 2496  const char *device = cfg.
name.c_str();
 
 2500  uint8_t  vpdBuf[252];
 
 2501  char lu_id[64], serial[256], vendor[40], model[40];
 
 2504  memset(inqBuf, 0, 96);
 
 2511      PrintOut(LOG_INFO, 
"Device: %s, Both 36 and 64 byte INQUIRY failed; " 
 2512               "skip device [err=%d, %d]\n", device, err, err64);
 
 2516  version = (inqBuf[2] & 0x7f); 
 
 2518  avail_len = inqBuf[4] + 5;
 
 2519  len = (avail_len < req_len) ? avail_len : req_len;
 
 2521    PrintOut(LOG_INFO, 
"Device: %s, INQUIRY response less than 36 bytes; " 
 2522             "skip device\n", device);
 
 2526  int pdt = inqBuf[0] & 0x1f;
 
 2537    PrintOut(LOG_INFO, 
"Device: %s, not a disk like device [PDT=0x%x], " 
 2538             "skip\n", device, pdt);
 
 2549  if (version >= 0x3) {
 
 2552                            vpdBuf, 
sizeof(vpdBuf))) {
 
 2559                          vpdBuf, 
sizeof(vpdBuf))) {
 
 2561          vpdBuf[4 + len] = 
'\0';
 
 2576                     (
char *)&inqBuf[8], (
char *)&inqBuf[16], (
char *)&inqBuf[32],
 
 2577                     (lu_id[0] ? 
", lu id: " : 
""), (lu_id[0] ? lu_id : 
""),
 
 2578                     (serial[0] ? 
", S/N: " : 
""), (serial[0] ? serial : 
""),
 
 2579                     (si_str[0] ? 
", " : 
""), (si_str[0] ? si_str : 
""));
 
 2599      PrintOut(LOG_INFO, 
"Device: %s, NOT READY (e.g. spun down); skip device\n", device);
 
 2601      PrintOut(LOG_INFO, 
"Device: %s, NO MEDIUM present; skip device\n", device);
 
 2603      PrintOut(LOG_INFO, 
"Device: %s, BECOMING (but not yet) READY; skip device\n", device);
 
 2605      PrintOut(LOG_CRIT, 
"Device: %s, failed Test Unit Ready [err=%d]\n", device, err);
 
 2622             "Device: %s, Bad IEC (SMART) mode page, err=%d, skip device\n", 
 
 2631    PrintOut(LOG_INFO, 
"Device: %s, IE (SMART) not enabled, skip device\n" 
 2632                       "Try 'smartctl -s on %s' to turn on SMART features\n",
 
 2674    uint8_t currenttemp = 0;
 
 2675    uint8_t triptemp = 0;
 
 2678                    &asc, &ascq, ¤ttemp, &triptemp)) {
 
 2679      PrintOut(LOG_INFO, 
"Device: %s, unexpectedly failed to read SMART values\n", device);
 
 2684      PrintOut(LOG_INFO, 
"Device: %s, can't monitor Temperature, ignoring -W %d,%d,%d\n",
 
 2695      PrintOut(LOG_INFO, 
"Device: %s, does not support SMART Self-Test Log.\n", device);
 
 2710      PrintOut(LOG_INFO,
"Device: %s, could not disable autosave (set GLTSD bit).\n",device);
 
 2712      PrintOut(LOG_INFO,
"Device: %s, disabled autosave (set GLTSD bit).\n",device);
 
 2718      PrintOut(LOG_INFO,
"Device: %s, could not enable autosave (clear GLTSD bit).\n",device);
 
 2720      PrintOut(LOG_INFO,
"Device: %s, enabled autosave (cleared GLTSD bit).\n",device);
 
 2724  PrintOut(LOG_INFO, 
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n", device);
 
 2743        PrintOut(LOG_INFO, 
"Device: %s, state read from %s\n", device, cfg.
state_file.c_str());
 
 2759  uint64_t newcnt = 0)
 
 2763  unsigned want_entries = 64;
 
 2770  if (!read_entries) {
 
 2771    PrintOut(LOG_INFO, 
"Device: %s, Read %u entries from Error Information Log failed\n",
 
 2772      cfg.
name.c_str(), want_entries);
 
 2781  int err = 0, ign = 0;
 
 2782  for (
unsigned i = 0; i < read_entries; i++) {
 
 2802    PrintOut(LOG_INFO, 
"Device: %s, NVMe error [%u], count %" PRIu64 
", status 0x%04x: %s\n",
 
 2807  std::string msg = 
strprintf(
"Device: %s, NVMe error count increased from %" PRIu64 
" to %" PRIu64
 
 2808                              " (%d new, %d ignored, %" PRIu64 
" unknown)",
 
 2809                              cfg.
name.c_str(), oldcnt, newcnt, err, ign,
 
 2810                              (mincnt > oldcnt + 1 ? mincnt - oldcnt - 1 : 0));
 
 2813    PrintOut(LOG_INFO, 
"%s\n", msg.c_str());
 
 2816    PrintOut(LOG_CRIT, 
"%s\n", msg.c_str());
 
 2828  const char *name = cfg.
name.c_str();
 
 2835    PrintOut(LOG_INFO, 
"Device: %s, NVMe Identify Controller failed\n", name);
 
 2841  char model[40+1], serial[20+1], firmware[8+1];
 
 2847  char nsstr[32] = 
"", capstr[32] = 
"";
 
 2850    snprintf(nsstr, 
sizeof(nsstr), 
", NSID:%u", 
nsid);
 
 2857    cfg.*idinfo = 
strprintf(
"%s, S/N:%s, FW:%s%s%s%s", model, serial, firmware,
 
 2858                            nsstr, (capstr[0] ? 
", " : 
""), capstr);
 
 2859    if (!(nsstr[0] && id_ctrl.
nn == 1))
 
 2882    PrintOut(LOG_INFO, 
"Device: %s, failed to read NVMe SMART/Health Information\n", name);
 
 2890      PrintOut(LOG_INFO, 
"Device: %s, no Temperature sensors, ignoring -W %d,%d,%d\n",
 
 2900      PrintOut(LOG_INFO, 
"Device: %s, Error Information unavailable, ignoring -l [x]error\n", name);
 
 2914      PrintOut(LOG_INFO, 
"Device: %s, Read NVMe Self-test Log failed: %s\n", name,
 
 2919      PrintOut(LOG_INFO, 
"Device: %s, does not support NVMe Self-tests, ignoring%s%s%s%s\n", name,
 
 2920               (cfg.
selftest ? 
" -l selftest" : 
""),
 
 2938  PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n", name);
 
 2955      snprintf(nsstr, 
sizeof(nsstr), 
"-n%u", 
nsid);
 
 2960        PrintOut(LOG_INFO, 
"Device: %s, state read from %s\n", name, cfg.
state_file.c_str());
 
 2975  const char * name = cfg.
name.c_str();
 
 2979    MailWarning(cfg, state, 0, 
"TEST EMAIL from smartd for device: %s", name);
 
 2994          PrintOut(LOG_INFO, 
"Device: %s, is in %s mode, suspending checks\n", name, 
"STANDBY (OS)");
 
 3005  if (!device->
open()) {
 
 3008      PrintOut(LOG_INFO, 
"Device: %s, open() of %s device failed: %s\n", name, type, device->
get_errmsg());
 
 3009      MailWarning(cfg, state, 9, 
"Device: %s, unable to open %s device", name, type);
 
 3012      PrintOut(LOG_INFO, 
"Device: %s, removed %s device: %s\n", name, type, device->
get_errmsg());
 
 3016      PrintOut(LOG_INFO, 
"Device: %s, %s device still removed: %s\n", name, type, device->
get_errmsg());
 
 3021    PrintOut(LOG_INFO,
"Device: %s, opened %s device\n", name, type);
 
 3026    PrintOut(LOG_INFO, 
"Device: %s, reconnected %s device\n", name, type);
 
 3036                                         int errcnt, uint64_t hour)
 
 3038  const char * name = cfg.
name.c_str();
 
 3043    MailWarning(cfg, state, 8, 
"Device: %s, Read SMART Self-Test Log Failed", name);
 
 3049      PrintOut(LOG_CRIT, 
"Device: %s, Self-Test Log error count increased from %d to %d\n",
 
 3051      MailWarning(cfg, state, 3, 
"Device: %s, Self-Test Log error count increased from %d to %d",
 
 3055    else if (errcnt > 0 && state.
selfloghour != hour) {
 
 3063      PrintOut(LOG_CRIT, 
"Device: %s, new Self-Test Log error at hour timestamp %" PRIu64 
"\n",
 
 3065      MailWarning(cfg, state, 3, 
"Device: %s, new Self-Test Log error at hour timestamp %" PRIu64 
"\n",
 
 3073      PrintOut(LOG_INFO, 
"Device: %s, Self-Test Log error count decreased from %d to %d\n",
 
 3108  time_t now = (!usetime ? time(
nullptr) : usetime);
 
 3122  unsigned offsets[max_offsets] = {0, }, limits[max_offsets] = {0, };
 
 3123  unsigned num_offsets = 1; 
 
 3125    const char * q = strchr(p, 
':');
 
 3129    unsigned offset = 0, limit = 0; 
int n1 = -1, n2 = -1, n3 = -1;
 
 3130    sscanf(p, 
"%u%n-%n%u%n", &offset, &n1, &n2, &limit, &n3);
 
 3131    if (!(n1 == 3 && (n2 < 0 || (n3 == 3+1+3 && limit > 0))))
 
 3133    offsets[num_offsets] = offset; limits[num_offsets] = limit;
 
 3135    p += (n3 > 0 ? n3 : n1);
 
 3140  time_t testtime = 0;
 
 3145    for (
unsigned i = 0; i < num_offsets; i++) {
 
 3146      unsigned offset = offsets[i], limit = limits[i];
 
 3148      if (0 < limit && limit < delay)
 
 3153      int weekday = (tms->tm_wday ? tms->tm_wday : 7);
 
 3154      for (
int j = 0; j <= maxtest; j++) {
 
 3167        snprintf(pattern, 
sizeof(pattern), 
"%c/%02d/%02d/%1d/%02d",
 
 3168          test_type_chars[j], tms->tm_mon+1, tms->tm_mday, weekday, tms->tm_hour);
 
 3170          const unsigned len = 
sizeof(
"S/01/01/1/01") - 1;
 
 3171          snprintf(pattern + len, 
sizeof(pattern) - len, 
":%03u", offset);
 
 3173            snprintf(pattern + len + 4, 
sizeof(pattern) - len - 4, 
"-%03u", limit);
 
 3177          testtype = pattern[0];
 
 3192    if ((t += 3600) > now)
 
 3203    if (!usetime && (testtime / 3600) < (now / 3600)) {
 
 3205      PrintOut(LOG_INFO, 
"Device: %s, old test of type %c not run at %s, starting now.\n",
 
 3206        cfg.
name.c_str(), testtype, datebuf);
 
 3216  unsigned numdev = configs.size();
 
 3221  PrintOut(LOG_INFO, 
"\nNext scheduled self tests (at most 5 of each type per device):\n");
 
 3224  time_t now = time(
nullptr);
 
 3231    time_t testtime = now + seconds;
 
 3232    for (
unsigned i = 0; i < numdev; i++) {
 
 3242          PrintOut(LOG_INFO, 
"Device: %s, will do test %d of type %c at %s\n", cfg.
name.c_str(),
 
 3251  PrintOut(LOG_INFO, 
"\nTotals [%s - %s]:\n", datenow, date);
 
 3252  for (
unsigned i = 0; i < numdev; i++) {
 
 3254    bool ata = 
devices.at(i)->is_ata();
 
 3259      PrintOut(LOG_INFO, 
"Device: %s, will do %3d test%s of type %c\n", cfg.
name.c_str(),
 
 3271  const char *testname = 
nullptr;
 
 3272  const char *name = cfg.
name.c_str();
 
 3276    PrintOut(LOG_CRIT, 
"Device: %s, does not support Self-Tests\n", name);
 
 3281  if (1 == inProgress) {
 
 3282    PrintOut(LOG_INFO, 
"Device: %s, skip since Self-Test already in " 
 3283             "progress.\n", name);
 
 3289    testname = 
"Short Self";
 
 3293    testname = 
"Long Self";
 
 3299    PrintOut(LOG_CRIT, 
"Device: %s, not capable of %c Self-Test\n", name, 
 
 3306      PrintOut(LOG_CRIT, 
"Device: %s, not capable of %s-Test\n", name, 
 
 3315    PrintOut(LOG_CRIT, 
"Device: %s, execute %s-Test failed (err: %d)\n", name, 
 
 3320  PrintOut(LOG_INFO, 
"Device: %s, starting scheduled %s-Test.\n", name, testname);
 
 3329  const char *name = cfg.
name.c_str();
 
 3335    PrintOut(LOG_CRIT, 
"Device: %s, not capable of Offline or Self-Testing.\n", name);
 
 3340  int dotest = -1, mode = 0;
 
 3341  const char *testname = 
nullptr;
 
 3344    testname=
"Offline Immediate ";
 
 3351    testname=
"Conveyance Self-";
 
 3358    testname=
"Short Self-";
 
 3365    testname=
"Long Self-";
 
 3372  case 'c': 
case 'n': 
case 'r':
 
 3373    testname = 
"Selective Self-";
 
 3389    PrintOut(LOG_CRIT, 
"Device: %s, not capable of %sTest\n", name, testname);
 
 3394  if (15==(
data.self_test_exec_status >> 4)) {
 
 3396      PrintOut(LOG_INFO, 
"Device: %s, will not skip scheduled %sTest " 
 3397               "despite unclear Self-Test byte (SAMSUNG Firmware bug).\n", name, testname);
 
 3399      PrintOut(LOG_INFO, 
"Device: %s, skip scheduled %sTest; %1d0%% remaining of current Self-Test.\n",
 
 3400               name, testname, (
int)(
data.self_test_exec_status & 0x0f));
 
 3414      PrintOut(LOG_CRIT, 
"Device: %s, prepare %sTest failed\n", name, testname);
 
 3418    PrintOut(LOG_INFO, 
"Device: %s, %s test span at LBA %" PRIu64 
" - %" PRIu64 
" (%" PRIu64 
" sectors, %u%% - %u%% of disk).\n",
 
 3420      start, end, end - start + 1,
 
 3430    PrintOut(LOG_CRIT, 
"Device: %s, execute %sTest failed.\n", name, testname);
 
 3436  if (testtype == 
'O')
 
 3441  PrintOut(LOG_INFO, 
"Device: %s, starting scheduled %sTest.\n", name, testname);
 
 3447                          unsigned char id, 
bool increase_only,
 
 3449                          int mailtype, 
const char * msg)
 
 3465  if (!(!increase_only || prev_rawval < rawval))
 
 3469  std::string 
s = 
strprintf(
"Device: %s, %" PRId64 
" %s", cfg.
name.c_str(), rawval, msg);
 
 3470  if (prev_rawval > 0 && rawval != prev_rawval)
 
 3471    s += 
strprintf(
" (changed %+" PRId64 
")", rawval - prev_rawval);
 
 3479static const char * 
fmt_temp(
unsigned char x, 
char (& buf)[20])
 
 3483  snprintf(buf, 
sizeof(buf), 
"%u", x);
 
 3490  if (!(0 < currtemp && currtemp < 255)) {
 
 3491    PrintOut(LOG_INFO, 
"Device: %s, failed to read Temperature\n", cfg.
name.c_str());
 
 3496  const char * minchg = 
"", * maxchg = 
"";
 
 3497  if (currtemp > state.
tempmax) {
 
 3510    PrintOut(LOG_INFO, 
"Device: %s, initial Temperature is %d Celsius (Min/Max %s/%u%s)\n",
 
 3513      PrintOut(LOG_INFO, 
"    [trip Temperature is %d Celsius]\n", (
int)triptemp);
 
 3537      PrintOut(LOG_INFO, 
"Device: %s, Temperature changed %+d Celsius to %u Celsius (Min/Max %s%s/%u%s)\n",
 
 3545    PrintOut(LOG_CRIT, 
"Device: %s, Temperature %u Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)\n",
 
 3547    MailWarning(cfg, state, 12, 
"Device: %s, Temperature %d Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)",
 
 3551    PrintOut(LOG_INFO, 
"Device: %s, Temperature %u Celsius reached limit of %u Celsius (Min/Max %s%s/%u%s)\n",
 
 3556    if (currtemp < limit)
 
 3557      reset_warning_mail(cfg, state, 12, 
"Temperature %u Celsius dropped below %u Celsius", currtemp, limit);
 
 3577    PrintOut(LOG_CRIT, 
"Device: %s, Failed SMART usage Attribute: %d %s.\n", cfg.
name.c_str(), attr.
id, attrname.c_str());
 
 3578    MailWarning(cfg, state, 2, 
"Device: %s, Failed SMART usage Attribute: %d %s.", cfg.
name.c_str(), attr.
id, attrname.c_str());
 
 3584  if (!(   ( prefail && cfg.
prefail)
 
 3585        || (!prefail && cfg.
usage  )))
 
 3593  if (attr.
id != prev.
id) {
 
 3594    PrintOut(LOG_INFO,
"Device: %s, same Attribute has different ID numbers: %d = %d\n",
 
 3595             cfg.
name.c_str(), attr.
id, prev.
id);
 
 3600  bool valchanged = 
false;
 
 3607  bool rawchanged = 
false;
 
 3615  if (!(valchanged || rawchanged))
 
 3619  std::string currstr, prevstr;
 
 3641  std::string msg = 
strprintf(
"Device: %s, SMART %s Attribute: %d %s changed from %s to %s",
 
 3642                              cfg.
name.c_str(), (prefail ? 
"Prefailure" : 
"Usage"), attr.
id,
 
 3644                              prevstr.c_str(), currstr.c_str());
 
 3649    PrintOut(LOG_CRIT, 
"%s\n", msg.c_str());
 
 3653    PrintOut(LOG_INFO, 
"%s\n", msg.c_str());
 
 3660                          bool firstpass, 
bool allow_selftests)
 
 3665  const char * name = cfg.
name.c_str();
 
 3672    const char * mode = 0;
 
 3673    if (0 <= powermode && powermode < 0xff) {
 
 3678      if (powermode2 > powermode)
 
 3679        PrintOut(LOG_INFO, 
"Device: %s, CHECK POWER STATUS spins up disk (0x%02x -> 0x%02x)\n", name, powermode, powermode2);
 
 3680      powermode = powermode2;
 
 3732      mode=
"ACTIVE or IDLE";
 
 3736      PrintOut(LOG_CRIT, 
"Device: %s, CHECK POWER STATUS returned %d, not ATA compliant, ignoring -n Directive\n",
 
 3749          PrintOut(LOG_INFO, 
"Device: %s, is in %s mode, suspending checks\n", name, mode);
 
 3756        PrintOut(LOG_INFO, 
"Device: %s, %s mode ignored due to reached limit of skipped checks (%d check%s skipped)\n",
 
 3763      PrintOut(LOG_INFO, 
"Device: %s, is back in %s mode, resuming checks (%d check%s skipped)\n",
 
 3774      PrintOut(LOG_INFO,
"Device: %s, not capable of SMART self-check\n",name);
 
 3775      MailWarning(cfg, state, 5, 
"Device: %s, not capable of SMART self-check", name);
 
 3778    else if (status==1){
 
 3779      PrintOut(LOG_CRIT, 
"Device: %s, FAILED SMART self-check. BACK UP DATA NOW!\n", name);
 
 3780      MailWarning(cfg, state, 1, 
"Device: %s, FAILED SMART self-check. BACK UP DATA NOW!", name);
 
 3794      PrintOut(LOG_CRIT, 
"Device: %s, failed to read SMART Attribute Data\n", name);
 
 3795      MailWarning(cfg, state, 6, 
"Device: %s, failed to read SMART Attribute Data", name);
 
 3805                                              : 
"Total unreadable (pending) sectors"    ));
 
 3810                                              : 
"Total offline uncorrectable sectors"));
 
 3861    int errcnt1 = -1, errcnt2 = -1;
 
 3868    int newc = (errcnt1 >= errcnt2 ? errcnt1 : errcnt2);
 
 3873      MailWarning(cfg, state, 7, 
"Device: %s, Read SMART Error Log Failed", name);
 
 3878      PrintOut(LOG_CRIT, 
"Device: %s, ATA error count increased from %d to %d\n",
 
 3880      MailWarning(cfg, state, 4, 
"Device: %s, ATA error count increased from %d to %d",
 
 3908  const char * name = cfg.
name.c_str();
 
 3910  uint8_t asc = 0, ascq = 0;
 
 3911  uint8_t currenttemp = 0, triptemp = 0;
 
 3914                    &asc, &ascq, ¤ttemp, &triptemp)) {
 
 3915      PrintOut(LOG_INFO, 
"Device: %s, failed to read SMART values\n",
 
 3917      MailWarning(cfg, state, 6, 
"Device: %s, failed to read SMART values", name);
 
 3926      PrintOut(LOG_CRIT, 
"Device: %s, SMART Failure: %s\n", name, cp);
 
 3927      MailWarning(cfg, state, 1,
"Device: %s, SMART Failure: %s", name, cp);
 
 3928    } 
else if (asc == 4 && ascq == 9) {
 
 3929      PrintOut(LOG_INFO,
"Device: %s, self-test in progress\n", name);
 
 3931      PrintOut(LOG_INFO,
"Device: %s, non-SMART asc,ascq: %d,%d\n",
 
 3932               name, (
int)asc, (
int)ascq);
 
 3934    PrintOut(LOG_INFO,
"Device: %s, SMART health: passed\n", name);
 
 4003  const char * valname, uint64_t oldval, uint64_t newval,
 
 4004  bool critical, 
bool info = 
true)
 
 4006  if (!(newval != oldval && (critical || info)))
 
 4009  std::string msg = 
strprintf(
"Device: %s, SMART/Health value: %s changed " 
 4010                              "from %" PRIu64 
" to %" PRIu64,
 
 4011                              cfg.
name.c_str(), valname, oldval, newval);
 
 4013    PrintOut(LOG_INFO, 
"%s\n", msg.c_str());
 
 4015    PrintOut(LOG_CRIT, 
"%s\n", msg.c_str());
 
 4032        || (firstpass && (
debugmode || curr_op))))
 
 4041  uint8_t op = (curr_op ? curr_op : op0);
 
 4042  const char * t; 
char tb[32];
 
 4044    case 0x0: t = 
""; 
break;
 
 4045    case 0x1: t = 
"short"; 
break;
 
 4046    case 0x2: t = 
"extended"; 
break;
 
 4047    case 0xe: t = 
"vendor specific"; 
break;
 
 4048    default:  snprintf(tb, 
sizeof(tb), 
"unknown (0x%x)", op);
 
 4053    PrintOut(LOG_INFO, 
"Device %s, %s self-test in progress, %d%% remaining\n",
 
 4054             name, t, 100 - curr_compl);
 
 4056  else if (!op0 || res0 == 0xf) { 
 
 4057    PrintOut(LOG_INFO, 
"Device %s, no self-test has ever been run\n", name);
 
 4061    const char * m; 
char mb[48];
 
 4063      case 0x0: m = 
"completed without error"; 
break;
 
 4064      case 0x1: m = 
"was aborted by a self-test command"; 
break;
 
 4065      case 0x2: m = 
"was aborted by a controller reset"; 
break;
 
 4066      case 0x3: m = 
"was aborted due to a namespace removal"; 
break;
 
 4067      case 0x4: m = 
"was aborted by a format NVM command"; 
break;
 
 4068      case 0x5: m = 
"completed with error (fatal or unknown error)"; 
break;
 
 4069      case 0x6: m = 
"completed with error (unknown failed segment)"; 
break;
 
 4070      case 0x7: m = 
"completed with error (failed segments)"; 
break;
 
 4071      case 0x8: m = 
"was aborted (unknown reason)"; 
break;
 
 4072      case 0x9: m = 
"was aborted due to a sanitize operation"; 
break;
 
 4073      default:  snprintf(mb, 
sizeof(mb), 
"returned an unknown result (0x%x)", res0);
 
 4079      snprintf(ns, 
sizeof(ns), 
" of NSID 0x%x", r.
nsid);
 
 4081    PrintOut((0x5 <= res0 && res0 <= 0x7 ? LOG_CRIT : LOG_INFO),
 
 4082             "Device %s, previous %s self-test%s %s\n", name, t, ns, m);
 
 4094  for (
unsigned i = 0; i < 20; i++) {
 
 4098    if (!op || res == 0xf)
 
 4102          || !(r.
valid & 0x01) 
 
 4106    if (op == 0x2  && !res )
 
 4109    if (!(0x5 <= res && res <= 0x7))
 
 4126  const char *name = cfg.
name.c_str();
 
 4129  const char *testname; uint8_t stc;
 
 4131    case 'S': testname = 
"Short";    stc = 1; 
break;
 
 4132    case 'L': testname = 
"Extended"; stc = 2; 
break;
 
 4134      PrintOut(LOG_INFO, 
"Device: %s, not capable of %c Self-Test\n", name, testtype);
 
 4140    PrintOut(LOG_INFO, 
"Device: %s, skip scheduled %s Self-Test (NSID 0x%x); %d%% remaining of current Self-Test.\n",
 
 4146    PrintOut(LOG_CRIT, 
"Device: %s, execute %s Self-Test failed (NSID 0x%x): %s.\n",
 
 4156  PrintOut(LOG_INFO, 
"Device: %s, starting scheduled %s Self-Test (NSID 0x%x).\n",
 
 4157           name, testname, 
nsid);
 
 4166  const char * name = cfg.
name.c_str();
 
 4173      PrintOut(LOG_INFO, 
"Device: %s, failed to read NVMe SMART/Health Information\n", name);
 
 4174      MailWarning(cfg, state, 6, 
"Device: %s, failed to read NVMe SMART/Health Information", name);
 
 4183    static const char * 
const wnames[8] = {
 
 4184      "LowSpare", 
"Temperature", 
"Reliability", 
"R/O",
 
 4185      "VolMemBackup", 
"PersistMem", 
"Bit_6", 
"Bit_7" 
 4188    for (
unsigned b = 0, cnt = 0; 
b < 8 ; 
b++) {
 
 4189      uint8_t mask = 1 << 
b;
 
 4195        msg += 
"..."; 
break;
 
 4204    PrintOut(LOG_CRIT, 
"Device: %s, Critical Warning (0x%02x): %s\n", name, 
w, msg.c_str());
 
 4205    MailWarning(cfg, state, 1, 
"Device: %s, Critical Warning (0x%02x): %s", name, 
w, msg.c_str());
 
 4233    int c = (int)k - 273;
 
 4249      PrintOut(LOG_CRIT, 
"Device: %s, Read Self-test Log failed: %s\n",
 
 4251      MailWarning(cfg, state, 8, 
"Device: %s, Read Self-test Log failed: %s\n",
 
 4300  bool sts1 = 
false, sts2 = 
false;
 
 4301  for (
const auto & cfg : configs) {
 
 4302    if (cfg.offlinests_ns)
 
 4304    if (cfg.selfteststs_ns)
 
 4311   if (!
smi()->disable_system_auto_standby(
false)) {
 
 4313        PrintOut(LOG_CRIT, 
"System auto standby enable failed: %s\n", 
smi()->get_errmsg());
 
 4315        PrintOut(LOG_INFO, 
"Disable auto standby not supported, ignoring ',ns' from %s%s%s\n",
 
 4316          (sts1 ? 
"-l offlinests,ns" : 
""), (sts1 && sts2 ? 
" and " : 
""), (sts2 ? 
"-l selfteststs,ns" : 
""));
 
 4317        sts1 = sts2 = 
false;
 
 4331  bool running = 
false;
 
 4332  for (
unsigned i = 0; i < configs.size() && !running; i++) {
 
 4348      if (!
smi()->disable_system_auto_standby(
false))
 
 4349        PrintOut(LOG_CRIT, 
"Self-test(s) completed, system auto standby enable failed: %s\n",
 
 4350                 smi()->get_errmsg());
 
 4352        PrintOut(LOG_INFO, 
"Self-test(s) completed, system auto standby enabled\n");
 
 4356  else if (!
smi()->disable_system_auto_standby(
true)) {
 
 4358      PrintOut(LOG_INFO, 
"Self-test(s) in progress, system auto standby disable rejected: %s\n",
 
 4359               smi()->get_errmsg());
 
 4365      PrintOut(LOG_INFO, 
"Self-test(s) in progress, system auto standby disabled\n");
 
 4375  for (
unsigned i = 0; i < configs.size(); i++) {
 
 4380        PrintOut(LOG_INFO, 
"Device: %s, skipped (interval=%d)\n", cfg.
name.c_str(),
 
 4421static void ToggleDebugMode()
 
 4424    PrintOut(LOG_INFO,
"Signal USR2 - enabling debug mode\n");
 
 4425    if (!daemon_enable_console(
"smartd [Debug]")) {
 
 4428      PrintOut(LOG_INFO,
"smartd debug mode enabled, PID=%d\n", getpid());
 
 4431      PrintOut(LOG_INFO,
"enable console failed\n");
 
 4434    daemon_disable_console();
 
 4437    PrintOut(LOG_INFO,
"Signal USR2 - debug mode disabled\n");
 
 4446  if (timenow < wakeuptime)
 
 4448  return timenow + ct - (timenow - wakeuptime) % ct;
 
 4455  time_t timenow = time(
nullptr);
 
 4456  unsigned n = configs.size();
 
 4466    for (
unsigned i = 0; i < n; i++) {
 
 4472      if (!wakeuptime || state.
wakeuptime < wakeuptime)
 
 4481  bool no_skip = 
false;
 
 4485    if (wakeuptime > timenow + ct) {
 
 4486      PrintOut(LOG_INFO, 
"System clock time adjusted to the past. Resetting next wakeup time.\n");
 
 4487      wakeuptime = timenow + ct;
 
 4488      for (
auto & state : states)
 
 4489        state.wakeuptime = 0;
 
 4494    sleep(wakeuptime+addtime-timenow);
 
 4498    if (caughtsigUSR2) {
 
 4504    timenow = time(
nullptr);
 
 4507    if (!addtime && timenow > wakeuptime+60) {
 
 4509        PrintOut(LOG_INFO, 
"Sleep time was %d seconds too long, assuming wakeup from standby mode.\n",
 
 4510          (
int)(timenow-wakeuptime));
 
 4512      addtime = timenow-wakeuptime+20;
 
 4514      int nextcheck = ct - addtime % ct;
 
 4515      if (nextcheck <= 20)
 
 4516        addtime += nextcheck;
 
 4522    PrintOut(LOG_INFO,
"Signal USR1 - checking devices now rather than in %d seconds.\n",
 
 4523             wakeuptime-timenow>0?(
int)(wakeuptime-timenow):0);
 
 4525    sigwakeup = no_skip = 
true;
 
 4530    for (
auto & state : states)
 
 4531      state.skip = (!no_skip && timenow < state.wakeuptime);
 
 4543    PrintOut(priority, 
"never[,N][,q], sleep[,N][,q], standby[,N][,q], idle[,N][,q]");
 
 4546    PrintOut(priority, 
"valid_regular_expression");
 
 4549    PrintOut(priority, 
"%s", 
smi()->get_valid_dev_types_str().c_str());
 
 4552    PrintOut(priority, 
"normal, permissive");
 
 4559    PrintOut(priority, 
"error, selftest");
 
 4562    PrintOut(priority, 
"\"once\", \"always\", \"daily\", \"diminishing\", \"test\", \"exec\"");
 
 4568    PrintOut(priority, 
"use, ignore, show, showall");
 
 4574    PrintOut(priority, 
"aam,[N|off], apm,[N|off], lookahead,[on|off], dsn,[on|off] " 
 4575                       "security-freeze, standby,[N|off], wcache,[on|off]");
 
 4578    PrintOut(priority, 
"i=N, interval=N");
 
 4584static int GetInteger(
const char *arg, 
const char *name, 
const char *token, 
int lineno, 
const char *cfgfile,
 
 4585               int min, 
int max, 
char * suffix = 0)
 
 4589    PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s takes integer argument from %d to %d.\n",
 
 4590             cfgfile, lineno, name, token, min, max);
 
 4596  int val = strtol(arg,&endptr,10);
 
 4600    if (!strcmp(endptr, suffix))
 
 4601      endptr += strlen(suffix);
 
 4606  if (!(!*endptr && min <= val && val <= max)) {
 
 4607    PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s has argument: %s; needs integer from %d to %d.\n",
 
 4608             cfgfile, lineno, name, token, arg, min, max);
 
 4618static int Get3Integers(
const char *arg, 
const char *name, 
const char *token, 
int lineno, 
const char *cfgfile,
 
 4619                 unsigned char *val1, 
unsigned char *val2, 
unsigned char *val3)
 
 4621  unsigned v1 = 0, v2 = 0, v3 = 0;
 
 4622  int n1 = -1, n2 = -1, n3 = -1, len;
 
 4624    PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s takes 1-3 integer argument(s) from 0 to 255.\n",
 
 4625             cfgfile, lineno, name, token);
 
 4630  if (!(   sscanf(arg, 
"%u%n,%u%n,%u%n", &v1, &n1, &v2, &n2, &v3, &n3) >= 1
 
 4631        && (n1 == len || n2 == len || n3 == len) && v1 <= 255 && v2 <= 255 && v3 <= 255)) {
 
 4632    PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s has argument: %s; needs 1-3 integer(s) from 0 to 255.\n",
 
 4633             cfgfile, lineno, name, token, arg);
 
 4636  *val1 = (
unsigned char)v1; *val2 = (
unsigned char)v2; *val3 = (
unsigned char)v3;
 
 4644static const char * strtok_dequote(
const char * delimiters)
 
 4646  const char * t = strtok(
nullptr, delimiters);
 
 4647  if (!t || t[0] != 
'"')
 
 4650  static std::string token;
 
 4653    t = strtok(
nullptr, delimiters);
 
 4657    int len = strlen(t);
 
 4658    if (t[len-1] == 
'"') {
 
 4659      token += std::string(t, len-1);
 
 4664  return token.c_str();
 
 4676  const char * name = cfg.
name.c_str();
 
 4678  const char *delim = 
" \n\t";
 
 4681  const char *arg = 0;
 
 4685    token = strtok(
nullptr, delim);
 
 4695  if (*token!=
'-' || strlen(token)!=2) {
 
 4696    PrintOut(LOG_CRIT,
"File %s line %d (drive %s): unknown Directive: %s\n",
 
 4698    PrintOut(LOG_CRIT, 
"Run smartd -D to print a list of valid Directives.\n");
 
 4707  char plus[] = 
"+", excl[] = 
"!";
 
 4712    if ((val = 
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno, 
configfile, 0, 255, plus)) < 0)
 
 4720    if ((val = 
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno, 
configfile, 0, 255, plus)) < 0)
 
 4728    if (!(arg = strtok(
nullptr, delim))) {
 
 4730    } 
else if (!strcmp(arg, 
"normal")) {
 
 4735    } 
else if (!strcmp(arg, 
"permissive")) {
 
 4744    if (!(arg = strtok(
nullptr, delim))) {
 
 4746    } 
else if (!strcmp(arg, 
"ignore")) {
 
 4748    } 
else if (!strcmp(arg, 
"removable")) {
 
 4750    } 
else if (!strcmp(arg, 
"auto")) {
 
 4755      scan_types.push_back(arg);
 
 4760    if (!(arg = strtok(
nullptr, delim)))
 
 4771      char * next_token = strtok(
nullptr, delim);
 
 4774      if (*next_token == 
'-') {
 
 4780      unsigned u = ~0; 
int nc = -1;
 
 4781      sscanf(arg, 
"0x%x%n", &u, &nc);
 
 4782      if (nc == (
int)strlen(arg) && u <= 0xff)
 
 4807    if (!(arg = strtok(
nullptr, delim))) {
 
 4809    } 
else if (!strcmp(arg, 
"selftest")) {
 
 4812    } 
else if (!strcmp(arg, 
"error")) {
 
 4815    } 
else if (!strcmp(arg, 
"xerror")) {
 
 4818    } 
else if (!strcmp(arg, 
"offlinests")) {
 
 4821    } 
else if (!strcmp(arg, 
"offlinests,ns")) {
 
 4824    } 
else if (!strcmp(arg, 
"selfteststs")) {
 
 4827    } 
else if (!strcmp(arg, 
"selfteststs,ns")) {
 
 4830    } 
else if (!strncmp(arg, 
"scterc,", 
sizeof(
"scterc,")-1)) {
 
 4832        unsigned rt = ~0, wt = ~0; 
int nc = -1;
 
 4833        sscanf(arg,
"scterc,%u,%u%n", &rt, &wt, &nc);
 
 4834        if (nc == (
int)strlen(arg) && rt <= 999 && wt <= 999) {
 
 4858    if (!(arg = strtok(
nullptr, delim))) {
 
 4860    } 
else if (!strcmp(arg, 
"on")) {
 
 4862    } 
else if (!strcmp(arg, 
"off")) {
 
 4870    if (!(arg = strtok(
nullptr, delim)))
 
 4873      char *endptr = 
nullptr;
 
 4874      char *next = strchr(
const_cast<char*
>(arg), 
',');
 
 4881      if (!strcmp(arg, 
"never"))
 
 4883      else if (!strcmp(arg, 
"sleep"))
 
 4885      else if (!strcmp(arg, 
"standby"))
 
 4887      else if (!strcmp(arg, 
"idle"))
 
 4893      if (!badarg && next) {
 
 4899          next = endptr + (*endptr != 
'\0');
 
 4903        if (*next != 
'\0') {
 
 4904          if (!strcmp(
"q", next))
 
 4915    if (!(arg = strtok(
nullptr, delim))) {
 
 4917    } 
else if (!strcmp(arg, 
"on")) {
 
 4919    } 
else if (!strcmp(arg, 
"off")) {
 
 4928      PrintOut(LOG_INFO, 
"File %s line %d (drive %s): ignoring previous Test Directive -s %s\n",
 
 4933    if (!(arg = strtok(
nullptr, delim))) {
 
 4940        PrintOut(LOG_CRIT, 
"File %s line %d (drive %s): -s argument \"%s\" is INVALID extended regular expression. %s.\n",
 
 4949        "[^]$()*+./:?^[|0-9LSCOncr-]+|" 
 4950        ":[0-9]{0,2}($|[^0-9])|:[0-9]{4,}|" 
 4951        ":[0-9]{3}-(000|[0-9]{0,2}($|[^0-9])|[0-9]{4,})" 
 4954      if (syntax_check.
execute(arg, 1, &range) && 0 <= range.rm_so && range.rm_so < range.rm_eo)
 
 4955        PrintOut(LOG_INFO,  
"File %s line %d (drive %s): warning, \"%.*s\" looks odd in " 
 4956                            "extended regular expression \"%s\"\n",
 
 4957                 configfile, lineno, name, (
int)(range.rm_eo - range.rm_so), arg + range.rm_so, arg);
 
 4962    if (!(arg = strtok(
nullptr, delim)))
 
 4966        PrintOut(LOG_INFO, 
"File %s line %d (drive %s): ignoring previous Address Directive -m %s\n",
 
 4973    if (!(arg = strtok(
nullptr, delim)))
 
 4975    else if (!strcmp(arg, 
"once"))
 
 4977    else if (!strcmp(arg, 
"always"))
 
 4979    else if (!strcmp(arg, 
"daily"))
 
 4981    else if (!strcmp(arg, 
"diminishing"))
 
 4983    else if (!strcmp(arg, 
"test"))
 
 4985    else if (!strcmp(arg, 
"exec")) {
 
 4989      arg = strtok_dequote(delim);
 
 4990      if (arg && arg[0] == 
'"') {
 
 4991        PrintOut(LOG_CRIT, 
"File %s line %d (drive %s): Directive %s 'exec' argument: missing closing quote\n",
 
 4996      arg = strtok(
nullptr, delim);
 
 4999        PrintOut(LOG_CRIT, 
"File %s line %d (drive %s): Directive %s 'exec' argument must be followed by executable path.\n",
 
 5005        PrintOut(LOG_INFO, 
"File %s line %d (drive %s): ignoring previous mail Directive -M exec %s\n",
 
 5014    if ((val = 
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno, 
configfile, 1, 255)) < 0)
 
 5020    if ((val = 
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno, 
configfile, 1, 255)) < 0)
 
 5026    if ((val = 
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno, 
configfile, 1, 255, excl)) < 0)
 
 5034    if ((val = 
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno, 
configfile, 1, 255, excl)) < 0)
 
 5048    if (!(arg = strtok(
nullptr, delim))) {
 
 5056    if (!(arg = strtok(
nullptr, delim))) {
 
 5058    } 
else if (!strcmp(arg, 
"use")) {
 
 5060    } 
else if (!strcmp(arg, 
"ignore")) {
 
 5062    } 
else if (!strcmp(arg, 
"show")) {
 
 5064    } 
else if (!strcmp(arg, 
"showall")) {
 
 5073    if (!(arg = strtok(
nullptr, delim))) {
 
 5077      char arg2[16+1]; 
unsigned uval;
 
 5078      int n1 = -1, n2 = -1, n3 = -1, len = strlen(arg);
 
 5079      if (sscanf(arg, 
"%16[^,=]%n%*[,=]%n%u%n", arg2, &n1, &n2, &uval, &n3) >= 1
 
 5080          && (n1 == len || n2 > 0)) {
 
 5081        bool on  = (n2 > 0 && !strcmp(arg+n2, 
"on"));
 
 5082        bool off = (n2 > 0 && !strcmp(arg+n2, 
"off"));
 
 5086        if (!strcmp(arg2, 
"aam")) {
 
 5089          else if (uval <= 254)
 
 5094        else if (!strcmp(arg2, 
"apm")) {
 
 5097          else if (1 <= uval && uval <= 254)
 
 5102        else if (!strcmp(arg2, 
"lookahead")) {
 
 5110        else if (!strcmp(arg, 
"security-freeze")) {
 
 5113        else if (!strcmp(arg2, 
"standby")) {
 
 5116          else if (uval <= 255)
 
 5121        else if (!strcmp(arg2, 
"wcache")) {
 
 5129        else if (!strcmp(arg2, 
"dsn")) {
 
 5148      if (!(arg = strtok(
nullptr, delim))) {
 
 5152      int n = 0, nc = -1, len = strlen(arg);
 
 5153      if (   (   sscanf(arg, 
"i=%d%n", &n, &nc) == 1
 
 5154              || sscanf(arg, 
"interval=%d%n", &n, &nc) == 1)
 
 5155          && nc == len && n >= 10)
 
 5164    PrintOut(LOG_CRIT,
"File %s line %d (drive %s): unknown Directive: %s\n",
 
 5166    PrintOut(LOG_CRIT, 
"Run smartd -D to print a list of valid Directives.\n");
 
 5170    PrintOut(LOG_CRIT, 
"File %s line %d (drive %s): Missing argument to %s Directive\n",
 
 5174    PrintOut(LOG_CRIT, 
"File %s line %d (drive %s): Invalid argument to %s Directive: %s\n",
 
 5177  if (missingarg || badarg) {
 
 5178    PrintOut(LOG_CRIT, 
"Valid arguments to %s Directive are: ", token);
 
 5190#define SCANDIRECTIVE "DEVICESCAN" 
 5204  const char *delim = 
" \n\t";
 
 5207  const char * name = strtok(line, delim);
 
 5208  if (!name || *name == 
'#')
 
 5213  if (!strcmp(
"DEFAULT", name)) {
 
 5221    conf_entries.push_back(default_conf);
 
 5223  dev_config & cfg = (retval ? conf_entries.back() : default_conf);
 
 5231  for (
char * token = 
nullptr; (rc = 
ParseToken(token, cfg, scan_types)) != 0; ) {
 
 5238  if (retval != -1 && scan_types.size() > 1) {
 
 5239    PrintOut(LOG_CRIT, 
"Drive: %s, invalid multiple -d TYPE Directives on line %d of file %s\n",
 
 5255    PrintOut(LOG_INFO,
"Drive: %s, implied '-a' Directive on line %d of file %s\n",
 
 5271    PrintOut(LOG_CRIT,
"Drive: %s, -M Directive(s) on line %d of file %s need -m ADDRESS Directive\n",
 
 5280      PrintOut(LOG_CRIT,
"Drive: %s, -m <nomailer> Directive on line %d of file %s needs -M exec Directive\n",
 
 5305  const int MAXLINELEN = 256;
 
 5307  const int MAXCONTLINE = 1023;
 
 5314      int ret = (errno!=ENOENT ? -3 : -2);
 
 5315      PrintOut(LOG_CRIT,
"%s: Unable to open configuration file %s\n",
 
 5331    if (
ParseConfigLine(conf_entries, default_conf, scan_types, 0, fakeconfig) != -1)
 
 5332      throw std::logic_error(
"Internal error parsing " SCANDIRECTIVE);
 
 5337  setmode(fileno(f), O_TEXT); 
 
 5344  int lineno = 1, cont = 0, contlineno = 0;
 
 5345  char line[MAXLINELEN+2];
 
 5346  char fullline[MAXCONTLINE+1];
 
 5349    int len=0,scandevice;
 
 5355    memset(line,0,
sizeof(line));
 
 5358    code=fgets(line, MAXLINELEN+2, f);
 
 5363        scandevice = 
ParseConfigLine(conf_entries, default_conf, scan_types, contlineno, fullline);
 
 5381    if (len>MAXLINELEN){
 
 5383      if (line[len-1]==
'\n')
 
 5384        warn=
"(including newline!) ";
 
 5387      PrintOut(LOG_CRIT,
"Error: line %d of file %s %sis more than MAXLINELEN=%d characters.\n",
 
 5388               (
int)contlineno,
configfile,warn,(
int)MAXLINELEN);
 
 5393    if ((comment=strchr(line,
'#'))){
 
 5399    if (cont+len>MAXCONTLINE){
 
 5400      PrintOut(LOG_CRIT,
"Error: continued line %d (actual line %d) of file %s is more than MAXCONTLINE=%d characters.\n",
 
 5401               lineno, (
int)contlineno, 
configfile, (
int)MAXCONTLINE);
 
 5406    snprintf(fullline+cont, 
sizeof(fullline)-cont, 
"%s" ,line);
 
 5410    if ( (lastslash=strrchr(line,
'\\')) && !strtok(lastslash+1,
" \n\t")){
 
 5411      *(fullline+(cont-len)+(lastslash-line))=
' ';
 
 5417    scandevice = 
ParseConfigLine(conf_entries, default_conf, scan_types, contlineno, fullline);
 
 5441  PrintOut(LOG_CRIT, 
"=======> VALID ARGUMENTS ARE: ");
 
 5443    PrintOut(LOG_CRIT, 
"Error constructing argument list for option %c", opt);
 
 5453  if (path.empty() || path[0] == 
'/')
 
 5458  PrintOut(LOG_CRIT, 
"=======> INVALID ARGUMENT TO -%c: %s <=======\n\n", option, path.c_str());
 
 5459  PrintOut(LOG_CRIT, 
"Error: relative path names are not allowed\n\n");
 
 5470  configfile = SMARTMONTOOLS_SYSCONFDIR 
"/smartd.conf";
 
 5471  warning_script = SMARTMONTOOLS_SMARTDSCRIPTDIR 
"/smartd_warning.sh";
 
 5474  static std::string configfile_str = exedir + 
"/smartd.conf";
 
 5480  static const char shortopts[] = 
"c:l:q:dDni:p:r:s:A:B:w:Vh?" 
 5481#if defined(HAVE_POSIX_API) || defined(_WIN32) 
 5484#ifdef HAVE_LIBCAP_NG 
 5489  struct option longopts[] = {
 
 5490    { 
"configfile",     required_argument, 0, 
'c' },
 
 5491    { 
"logfacility",    required_argument, 0, 
'l' },
 
 5492    { 
"quit",           required_argument, 0, 
'q' },
 
 5493    { 
"debug",          no_argument,       0, 
'd' },
 
 5494    { 
"showdirectives", no_argument,       0, 
'D' },
 
 5495    { 
"interval",       required_argument, 0, 
'i' },
 
 5497    { 
"no-fork",        no_argument,       0, 
'n' },
 
 5499    { 
"service",        no_argument,       0, 
'n' },
 
 5501    { 
"pidfile",        required_argument, 0, 
'p' },
 
 5502    { 
"report",         required_argument, 0, 
'r' },
 
 5503    { 
"savestates",     required_argument, 0, 
's' },
 
 5504    { 
"attributelog",   required_argument, 0, 
'A' },
 
 5505    { 
"drivedb",        required_argument, 0, 
'B' },
 
 5506    { 
"warnexec",       required_argument, 0, 
'w' },
 
 5507    { 
"version",        no_argument,       0, 
'V' },
 
 5508    { 
"license",        no_argument,       0, 
'V' },
 
 5509    { 
"copyright",      no_argument,       0, 
'V' },
 
 5510    { 
"help",           no_argument,       0, 
'h' },
 
 5511    { 
"usage",          no_argument,       0, 
'h' },
 
 5512#if defined(HAVE_POSIX_API) || defined(_WIN32) 
 5513    { 
"warn-as-user",   required_argument, 0, 
'u' },
 
 5515#ifdef HAVE_LIBCAP_NG 
 5516    { 
"capabilities",   optional_argument, 0, 
'C' },
 
 5522  bool badarg = 
false;
 
 5523  const char * badarg_msg = 
nullptr;
 
 5524  bool use_default_db = 
true; 
 
 5528  while ((optchar = getopt_long(argc, argv, shortopts, longopts, 
nullptr)) != -1) {
 
 5537      if (!strcmp(optarg, 
"nodev"))
 
 5539      else if (!strcmp(optarg, 
"nodev0")) {
 
 5543      else if (!strcmp(optarg, 
"nodevstartup"))
 
 5545      else if (!strcmp(optarg, 
"nodev0startup")) {
 
 5549      else if (!strcmp(optarg, 
"errors"))
 
 5551      else if (!strcmp(optarg, 
"errors,nodev0")) {
 
 5555      else if (!strcmp(optarg, 
"never"))
 
 5557      else if (!strcmp(optarg, 
"onecheck")) {
 
 5561      else if (!strcmp(optarg, 
"showtests")) {
 
 5570      if (!strcmp(optarg, 
"daemon"))
 
 5572      else if (!strcmp(optarg, 
"local0"))
 
 5574      else if (!strcmp(optarg, 
"local1"))
 
 5576      else if (!strcmp(optarg, 
"local2"))
 
 5578      else if (!strcmp(optarg, 
"local3"))
 
 5580      else if (!strcmp(optarg, 
"local4"))
 
 5582      else if (!strcmp(optarg, 
"local5"))
 
 5584      else if (!strcmp(optarg, 
"local6"))
 
 5586      else if (!strcmp(optarg, 
"local7"))
 
 5610      lchecktime = strtol(optarg, &tailptr, 10);
 
 5611      if (*tailptr != 
'\0' || lchecktime < 10 || lchecktime > INT_MAX || errno) {
 
 5614        PrintOut(LOG_CRIT, 
"======> INVALID INTERVAL: %s <=======\n", optarg);
 
 5615        PrintOut(LOG_CRIT, 
"======> INTERVAL MUST BE INTEGER BETWEEN %d AND %d <=======\n", 10, INT_MAX);
 
 5616        PrintOut(LOG_CRIT, 
"\nUse smartd -h to get a usage summary\n\n");
 
 5624        int n1 = -1, n2 = -1, len = strlen(optarg);
 
 5625        char s[9+1]; 
unsigned i = 1;
 
 5626        sscanf(optarg, 
"%9[a-z]%n,%u%n", 
s, &n1, &i, &n2);
 
 5627        if (!((n1 == len || n2 == len) && 1 <= i && i <= 4)) {
 
 5629        } 
else if (!strcmp(
s,
"ioctl")) {
 
 5631        } 
else if (!strcmp(
s,
"ataioctl")) {
 
 5633        } 
else if (!strcmp(
s,
"scsiioctl")) {
 
 5635        } 
else if (!strcmp(
s,
"nvmeioctl")) {
 
 5644      if (strcmp(optarg,
"-"))
 
 5663        const char * path = optarg;
 
 5664        if (*path == 
'+' && path[1])
 
 5667          use_default_db = 
false;
 
 5677#ifdef HAVE_POSIX_API 
 5679      warn_as_user = 
false;
 
 5680      if (strcmp(optarg, 
"-")) {
 
 5681        warn_uname = warn_gname = 
"unknown";
 
 5682        badarg_msg = 
parse_ugid(optarg, warn_uid, warn_gid,
 
 5683                                warn_uname, warn_gname     );
 
 5686        warn_as_user = 
true;
 
 5689#elif defined(_WIN32) 
 5691      if (!strcmp(optarg, 
"restricted"))
 
 5692        warn_as_restr_user = 
true;
 
 5693      else if (!strcmp(optarg, 
"unchanged"))
 
 5694        warn_as_restr_user = 
false;
 
 5704#ifdef HAVE_LIBCAP_NG 
 5708        capabilities_mode = 1;
 
 5709      else if (!strcmp(optarg, 
"mail"))
 
 5710        capabilities_mode = 2;
 
 5728      arg = argv[optind <= argc ? optind - 1 : argc - 1];
 
 5730      if (arg[1] == 
'-' && optchar != 
'h') {
 
 5732        if (optopt && strchr(shortopts, optopt)) {
 
 5733          PrintOut(LOG_CRIT, 
"=======> ARGUMENT REQUIRED FOR OPTION: %s <=======\n",arg+2);
 
 5736          PrintOut(LOG_CRIT, 
"=======> UNRECOGNIZED OPTION: %s <=======\n\n",arg+2);
 
 5738        PrintOut(LOG_CRIT, 
"\nUse smartd --help to get a usage summary\n\n");
 
 5743        if (strchr(shortopts, optopt)){
 
 5744          PrintOut(LOG_CRIT, 
"=======> ARGUMENT REQUIRED FOR OPTION: %c <=======\n",optopt);
 
 5747          PrintOut(LOG_CRIT, 
"=======> UNRECOGNIZED OPTION: %c <=======\n\n",optopt);
 
 5749        PrintOut(LOG_CRIT, 
"\nUse smartd -h to get a usage summary\n\n");
 
 5757    if (badarg || badarg_msg) {
 
 5763      PrintOut(LOG_CRIT, 
"=======> INVALID ARGUMENT TO -%c: %s <======= \n", optchar, optarg);
 
 5765        PrintOut(LOG_CRIT, 
"%s\n", badarg_msg);
 
 5768      PrintOut(LOG_CRIT, 
"\nUse smartd -h to get a usage summary\n\n");
 
 5774  if (argc > optind) {
 
 5777    PrintOut(LOG_CRIT, 
"=======> UNRECOGNIZED ARGUMENT: %s <=======\n\n", argv[optind]);
 
 5778    PrintOut(LOG_CRIT, 
"\nUse smartd -h to get a usage summary\n\n");
 
 5786    PrintOut(LOG_CRIT, 
"=======> INVALID CHOICE OF OPTIONS: -d and -p <======= \n\n");
 
 5787    PrintOut(LOG_CRIT, 
"Error: pid file %s not written in debug (-d) mode\n\n", 
pid_file.c_str());
 
 5802  if (warn_as_restr_user && !popen_as_restr_check()) {
 
 5805    PrintOut(LOG_CRIT, 
"Option '--warn-as-user=restricted' is not effective if the current user\n");
 
 5806    PrintOut(LOG_CRIT, 
"is the local 'SYSTEM' or 'Administrator' account\n\n");
 
 5840  if (!
smi()->scan_smart_devices(devlist, types)) {
 
 5841    PrintOut(LOG_CRIT, 
"DEVICESCAN failed: %s\n", 
smi()->get_errmsg());
 
 5846  if (devlist.
size() == 0)
 
 5850  while (scanned_devs.
size() < conf_entries.size())
 
 5854  for (
unsigned i = 0; i < devlist.
size(); i++) {
 
 5860    conf_entries.push_back(base_cfg);
 
 5873  return devlist.
size();
 
 5886    conf_entries.clear();
 
 5897  else if (!conf_entries.empty()) {
 
 5902    conf_entries.pop_back();
 
 5913    if (conf_entries.empty())
 
 5914      PrintOut(LOG_CRIT,
"In the system's table of devices NO devices found to scan\n");
 
 5919  return conf_entries.size();
 
 5932        PrintOut(LOG_INFO, 
"Device: %s, unable to autodetect device type\n", cfg.
name.c_str());
 
 5934        PrintOut(LOG_INFO, 
"Device: %s, unsupported device type '%s'\n", cfg.
name.c_str(), cfg.
dev_type.c_str());
 
 5948  dev.
replace( dev->autodetect_open() );
 
 5951  if (oldinfo.
dev_type != dev->get_dev_type())
 
 5952    PrintOut(LOG_INFO, 
"Device: %s, type changed from '%s' to '%s'\n",
 
 5953      cfg.
name.c_str(), oldinfo.
dev_type.c_str(), dev->get_dev_type());
 
 5956  if (!dev->is_open()) {
 
 5958      PrintOut(LOG_INFO, 
"Device: %s, open() failed: %s\n", dev->get_info_name(), dev->get_errmsg());
 
 5963  cfg.
name = dev->get_info().info_name;
 
 5964  PrintOut(LOG_INFO, 
"Device: %s, opened\n", cfg.
name.c_str());
 
 5967  const char * typemsg;
 
 5971    status = 
ATADeviceScan(cfg, state, dev->to_ata(), prev_cfgs);
 
 5974  else if (dev->is_scsi()){
 
 5979  else if (dev->is_nvme()) {
 
 5984    PrintOut(LOG_INFO, 
"Device: %s, neither ATA, SCSI nor NVMe device\n", cfg.
name.c_str());
 
 5991        PrintOut(scanning ? LOG_INFO : LOG_CRIT,
 
 5992          "Unable to register %s device %s at line %d of file %s\n",
 
 5995        PrintOut(LOG_INFO, 
"Unable to register %s device %s\n",
 
 5996          typemsg, cfg.
name.c_str());
 
 6017  typedef std::map<std::string, std::string> prev_unique_names_map;
 
 6018  prev_unique_names_map prev_unique_names;
 
 6021  for (
unsigned i = 0; i < conf_entries.size(); i++) {
 
 6027      pout(
"Device: %s%s%s%s, unique name: %s\n", cfg.
name.c_str(),
 
 6029           (!cfg.
dev_type.empty() ? 
"]" : 
""), unique_name.c_str());
 
 6034      PrintOut(LOG_INFO, 
"Device: %s%s%s%s, ignored\n", cfg.
name.c_str(),
 
 6036               (!cfg.
dev_type.empty() ? 
"]" : 
""));
 
 6037      prev_unique_names[unique_name] = cfg.
name;
 
 6044    bool scanning = 
false;
 
 6045    if (i < scanned_devs.
size()) {
 
 6046      dev = scanned_devs.
release(i);
 
 6049        prev_unique_names_map::iterator ui = prev_unique_names.find(unique_name);
 
 6050        if (ui != prev_unique_names.end()) {
 
 6051          bool ne = (ui->second != cfg.
name);
 
 6052          PrintOut(LOG_INFO, 
"Device: %s, %s%s, ignored\n", dev->get_info_name(),
 
 6053                   (ne ? 
"same as " : 
"duplicate"), (ne ? ui->second.c_str() : 
""));
 
 6071          PrintOut(LOG_CRIT, 
"Unable to register device %s (no Directive -d removable). Exiting.\n",
 
 6075        PrintOut(LOG_INFO, 
"Device: %s, not available\n", cfg.
name.c_str());
 
 6077        prev_unique_names[unique_name] = cfg.
name;
 
 6083    configs.push_back(cfg);
 
 6084    states.push_back(state);
 
 6088      prev_unique_names[unique_name] = cfg.
name;
 
 6093  unsigned factor = 0;
 
 6094  for (
auto & cfg : configs) {
 
 6097    if (!cfg.test_regex.empty())
 
 6098      cfg.test_offset_factor = factor++;
 
 6137  bool firstpass = 
true, write_states_always = 
true;
 
 6138  time_t wakeuptime = 0;
 
 6150                 "Signal HUP - rereading configuration file %s\n":
 
 6151                 "\a\nSignal INT - rereading configuration file %s (" SIGQUIT_KEYNAME " quits)\n\n",
 
 6168          if (!(configs.size() == 
devices.size() && configs.size() == states.size()))
 
 6169            throw std::logic_error(
"Invalid result from RegisterDevices");
 
 6175            PrintOut(LOG_INFO,
"Reusing previous configuration\n");
 
 6187        PrintOut((status ? LOG_CRIT : LOG_INFO),
 
 6188                 "Unable to monitor any SMART enabled devices. Exiting.\n");
 
 6193      int numata = 0, numscsi = 0;
 
 6194      for (
unsigned i = 0; i < 
devices.size(); i++) {
 
 6201      PrintOut(LOG_INFO, 
"Monitoring %d ATA/SATA, %d SCSI/SAS and %d NVMe devices\n",
 
 6202               numata, numscsi, (
int)
devices.size() - numata - numscsi);
 
 6215      write_states_always = 
true;
 
 6226    write_states_always = 
false;
 
 6234      PrintOut(LOG_INFO,
"Started with '-q onecheck' option. All devices successfully checked once.\n" 
 6235               "smartd is exiting (exit status 0)\n");
 
 6257      wakeuptime = time(
nullptr);
 
 6263    wakeuptime = 
dosleep(wakeuptime, configs, states, write_states_always);
 
 6270      PrintOut(LOG_INFO, 
"smartd received signal %d: %s\n",
 
 6275      PrintOut(LOG_CRIT, 
"smartd received unexpected signal %d: %s\n",
 
 6294        PrintOut(LOG_CRIT,
"Can't unlink PID file %s (%s).\n",
 
 6295                 pid_file.c_str(), strerror(errno));
 
 6298  PrintOut((status ? LOG_CRIT : LOG_INFO), 
"smartd is exiting (exit status %d)\n", status);
 
 6308static int smartd_main(
int argc, 
char **argv)
 
 6316  catch (
const std::bad_alloc & ) {
 
 6318    PrintOut(LOG_CRIT, 
"Smartd: Out of memory\n");
 
 6321  catch (
const std::exception & ex) {
 
 6323    PrintOut(LOG_CRIT, 
"Smartd: Exception: %s\n", ex.what());
 
 6329    PrintOut(LOG_CRIT, 
"Smartd: Internal Error: %d device object(s) left at exit.\n",
 
 6335    PrintOut(LOG_CRIT, 
"Please inform " PACKAGE_BUGREPORT 
", including output of smartd -V.\n");
 
 6339  daemon_winsvc_exitcode = status;
 
 6347int main(
int argc, 
char **argv){
 
 6349  static const daemon_winsvc_options svc_opts = {
 
 6351    "smartd", 
"SmartD Service", 
 
 6353    "Controls and monitors storage devices using the Self-Monitoring, " 
 6354    "Analysis and Reporting Technology System (SMART) built into " 
 6355    "ATA/SATA and SCSI/SAS hard drives and solid-state drives. " 
 6356    "www.smartmontools.org" 
 6361  return daemon_main(
"smartd", &svc_opts , smartd_main, argc, argv);
 
bool ata_nodata_command(ata_device *device, unsigned char command, int sector_count)
int ataDisableAutoOffline(ata_device *device)
unsigned char ata_return_temperature_value(const ata_smart_values *data, const ata_vendor_attr_defs &defs)
bool isSmartErrorLogCapable(const ata_smart_values *data, const ata_identify_device *identity)
int ata_get_wwn(const ata_identify_device *id, unsigned &oui, uint64_t &unique_id)
int ataEnableAutoOffline(ata_device *device)
int ataSmartStatus2(ata_device *device)
int ataSmartSupport(const ata_identify_device *drive)
int ataDisableAutoSave(ata_device *device)
int ata_get_rotation_rate(const ata_identify_device *id)
unsigned char get_unc_attr_id(bool offline, const ata_vendor_attr_defs &defs, bool &increase)
bool parse_attribute_def(const char *opt, ata_vendor_attr_defs &defs, ata_vendor_def_prior priority)
int ataEnableAutoSave(ata_device *device)
int ataReadSelfTestLog(ata_device *device, ata_smart_selftestlog *data, firmwarebug_defs firmwarebugs)
std::string ata_format_attr_raw_value(const ata_smart_attribute &attr, const ata_vendor_attr_defs &defs)
int ata_find_attr_index(unsigned char id, const ata_smart_values &smartval)
int ataReadErrorLog(ata_device *device, ata_smart_errorlog *data, firmwarebug_defs firmwarebugs)
void ata_get_size_info(const ata_identify_device *id, ata_size_info &sizes)
int ata_read_identity(ata_device *device, ata_identify_device *buf, bool fix_swapped_id, unsigned char *raw_buf)
int ataEnableSmart(ata_device *device)
int smartcommandhandler(ata_device *device, smart_command_set command, int select, char *data)
bool isGeneralPurposeLoggingCapable(const ata_identify_device *identity)
int ataCheckPowerMode(ata_device *device)
std::string create_vendor_attribute_arg_list()
bool isSmartTestLogCapable(const ata_smart_values *data, const ata_identify_device *identity)
int ataReadSmartValues(ata_device *device, struct ata_smart_values *data)
bool parse_firmwarebug_def(const char *opt, firmwarebug_defs &firmwarebugs)
int ataSetSCTErrorRecoveryControltime(ata_device *device, unsigned type, unsigned short time_limit, bool power_on, bool mfg_default)
unsigned char ata_debugmode
const char * get_valid_firmwarebug_args()
uint64_t ata_get_attr_raw_value(const ata_smart_attribute &attr, const ata_vendor_attr_defs &defs)
bool ataReadExtErrorLog(ata_device *device, ata_smart_exterrlog *log, unsigned page, unsigned nsectors, firmwarebug_defs firmwarebugs)
int ataWriteSelectiveSelfTestLog(ata_device *device, ata_selective_selftest_args &args, const ata_smart_values *sv, uint64_t num_sectors, const ata_selective_selftest_args *prev_args)
std::string ata_get_smart_attr_name(unsigned char id, const ata_vendor_attr_defs &defs, int rpm)
int ataReadSmartThresholds(ata_device *device, struct ata_smart_thresholds_pvt *data)
int ataIsSmartEnabled(const ata_identify_device *drive)
void ata_format_id_string(char *out, const unsigned char *in, int n)
int ataReadLogDirectory(ata_device *device, ata_smart_log_directory *data, bool gpl)
bool ata_set_features(ata_device *device, unsigned char features, int sector_count)
ata_attr_state ata_get_attr_state(const ata_smart_attribute &attr, int attridx, const ata_smart_threshold_entry *thresholds, const ata_vendor_attr_defs &defs, unsigned char *threshval)
#define ATA_ENABLE_READ_LOOK_AHEAD
#define ATA_DISABLE_WRITE_CACHE
bool isSupportSelfTest(const ata_smart_values *data)
#define SELECTIVE_SELF_TEST
bool isSCTErrorRecoveryControlCapable(const ata_identify_device *drive)
#define OFFLINE_FULL_SCAN
bool isSupportConveyanceSelfTest(const ata_smart_values *data)
#define ATA_ENABLE_DISABLE_DSN
bool isSupportAutomaticTimer(const ata_smart_values *data)
#define ATA_ENABLE_WRITE_CACHE
bool isSupportSelectiveSelfTest(const ata_smart_values *data)
#define ATA_DISABLE_READ_LOOK_AHEAD
#define ATTRIBUTE_FLAGS_PREFAILURE(x)
bool isSupportExecuteOfflineImmediate(const ata_smart_values *data)
#define CONVEYANCE_SELF_TEST
#define ATA_SECURITY_FREEZE_LOCK
#define NUMBER_ATA_SMART_ATTRIBUTES
Smart pointer class for device pointers.
void replace(device_type *dev)
Replace the pointer.
unsigned char m_flags[256]
bool is_set(int id, unsigned char flag) const
void set(int id, unsigned char flags)
env_buffer(const env_buffer &)=delete
void set(const char *name, const char *value)
void operator=(const env_buffer &)=delete
bool is_set(firmwarebug_t bug) const
unsigned get_nsid() const
Get namespace id.
Wrapper class for POSIX regex(3) or std::regex Supports copy & assignment and is compatible with STL ...
bool full_match(const char *str) const
Return true if full string matches pattern.
const char * get_errmsg() const
Get error message from last compile().
const char * get_pattern() const
bool compile(const char *pattern)
Set and compile new pattern, return false on error.
bool execute(const char *str, unsigned nmatch, match_range *pmatch) const
Return true if substring matches pattern, fill match_range array.
List of devices for DEVICESCAN.
void push_back(smart_device *dev)
smart_device * release(unsigned i)
Base class for all devices.
bool is_scsi() const
Return true if SCSI device.
virtual bool is_powered_down()
Early test if device is powered up or down.
bool is_nvme() const
Return true if NVMe device.
const device_info & get_info() const
Get device info struct.
const char * get_errmsg() const
Get last error message.
virtual bool close()=0
Close device, return false on error.
nvme_device * to_nvme()
Downcast to NVMe device.
ata_device * to_ata()
Downcast to ATA device.
scsi_device * to_scsi()
Downcast to SCSI device.
static int get_num_objects()
Get current number of allocated 'smart_device' objects.
bool is_ata() const
Return true if ATA device.
virtual bool open()=0
Open device, return false on error.
virtual std::string get_unique_dev_name(const char *name, const char *type) const
Return unique device name which is (only) suitable for duplicate detection.
virtual smart_device * get_smart_device(const char *name, const char *type)
Return device object for device 'name' with some 'type'.
static void init()
Initialize platform interface and register with smi().
Wrapper class for FILE *.
bool open(const char *name, const char *mode)
std::vector< std::string > smart_devtype_list
List of types for DEVICESCAN.
smart_interface * smi()
Global access to the (usually singleton) smart_interface.
const drive_settings * lookup_drive_apply_presets(const ata_identify_device *drive, ata_vendor_attr_defs &defs, firmwarebug_defs &firmwarebugs, std::string &dbversion)
bool init_drive_database(bool use_default_db)
const char * get_drivedb_path_add()
static bool match(const char *pattern, const char *str)
void show_presets(const ata_identify_device *drive)
bool read_drive_database(const char *path)
bool nvme_read_self_test_log(nvme_device *device, uint32_t nsid, smartmontools::nvme_self_test_log &self_test_log)
int nvme_status_to_errno(uint16_t status)
bool nvme_read_id_ctrl(nvme_device *device, nvme_id_ctrl &id_ctrl)
unsigned char nvme_debugmode
bool nvme_self_test(nvme_device *device, uint8_t stc, uint32_t nsid)
unsigned nvme_read_error_log(nvme_device *device, nvme_error_log_page *error_log, unsigned num_entries, bool lpo_sup)
bool nvme_read_smart_log(nvme_device *device, uint32_t nsid, nvme_smart_log &smart_log)
const char * nvme_status_to_info_str(char *buf, size_t bufsize, uint16_t status)
constexpr bool nvme_status_is_error(uint16_t status)
constexpr uint32_t nvme_broadcast_nsid
static struct @44 devices[20]
std::string get_exe_dir()
FILE * popen_as_ugid(const char *cmd, const char *mode, uid_t uid, gid_t gid)
int pclose_as_ugid(FILE *f)
const char * parse_ugid(const char *s, uid_t &uid, gid_t &gid, std::string &uname, std::string &gname)
void scsiDecodeErrCounterPage(unsigned char *resp, struct scsiErrorCounter *ecp, int allocLen)
int scsiFetchIECmpage(scsi_device *device, struct scsi_iec_mode_page *iecp, int modese_len)
int scsi_decode_lu_dev_id(const unsigned char *b, int blen, char *s, int slen, int *transport)
int scsiTestUnitReady(scsi_device *device)
int scsiInquiryVpd(scsi_device *device, int vpd_page, uint8_t *pBuf, int bufLen)
int scsiSmartExtendSelfTest(scsi_device *device)
void scsiDecodeNonMediumErrPage(unsigned char *resp, struct scsiNonMediumError *nmep, int allocLen)
int scsiCheckIE(scsi_device *device, int hasIELogPage, int hasTempLogPage, uint8_t *asc, uint8_t *ascq, uint8_t *currenttemp, uint8_t *triptemp)
uint64_t scsiGetSize(scsi_device *device, bool avoid_rcap16, struct scsi_readcap_resp *srrp)
int scsiSelfTestInProgress(scsi_device *fd, int *inProgress)
char * scsiGetIEString(uint8_t asc, uint8_t ascq, char *b, int blen)
supported_vpd_pages * supported_vpd_pages_p
void scsi_format_id_string(char *out, const uint8_t *in, int n)
int scsiStdInquiry(scsi_device *device, uint8_t *pBuf, int bufLen)
int scsiCountFailedSelfTests(scsi_device *fd, int noisy)
int scsiSetControlGLTSD(scsi_device *device, int enabled, int modese_len)
int scsi_IsExceptionControlEnabled(const struct scsi_iec_mode_page *iecp)
int scsiSmartShortSelfTest(scsi_device *device)
int scsiLogSense(scsi_device *device, int pagenum, int subpagenum, uint8_t *pBuf, int bufLen, int known_resp_len)
unsigned char scsi_debugmode
#define SIMPLE_ERR_BECOMING_READY
#define SIMPLE_ERR_BAD_FIELD
#define SIMPLE_ERR_NOT_READY
#define SCSI_VPD_DEVICE_IDENTIFICATION
#define SIMPLE_ERR_NO_MEDIUM
#define VERIFY_ERROR_COUNTER_LPAGE
#define SIMPLE_ERR_BAD_OPCODE
#define NON_MEDIUM_ERROR_LPAGE
#define SCSI_VPD_UNIT_SERIAL_NUMBER
#define SCSI_PT_HOST_MANAGED
#define TEMPERATURE_LPAGE
#define WRITE_ERROR_COUNTER_LPAGE
#define SCSI_PT_DIRECT_ACCESS
#define READ_ERROR_COUNTER_LPAGE
static uint64_t sg_get_unaligned_le64(const void *p)
static void sg_put_unaligned_le64(uint64_t val, void *p)
static uint16_t sg_get_unaligned_le16(const void *p)
static int CloseDevice(smart_device *device, const char *name)
static bool is_duplicate_dev_idinfo(const dev_config &cfg, const dev_config_vector &prev_cfgs)
static void reset_warning_mail(const dev_config &cfg, dev_state &state, int which, const char *fmt,...) __attribute_format_printf(4
unsigned char failuretest_permissive
const bool fix_swapped_id
static std::string state_path_prefix
static bool write_dev_state(const char *path, const persistent_dev_state &state)
static int NVMeDeviceScan(dev_config &cfg, dev_state &state, nvme_device *nvmedev, const dev_config_vector *prev_cfgs)
static std::string configfile_alt
static int Get3Integers(const char *arg, const char *name, const char *token, int lineno, const char *cfgfile, unsigned char *val1, unsigned char *val2, unsigned char *val3)
static void log_nvme_smart_change(const dev_config &cfg, dev_state &state, const char *valname, uint64_t oldval, uint64_t newval, bool critical, bool info=true)
static void sighandler(int sig)
static int check_ata_self_test_log(ata_device *device, const char *name, firmwarebug_defs firmwarebugs, unsigned &hour)
static const int MAILTYPE_TEST
static void do_disable_standby_check(const dev_config_vector &configs, const dev_state_vector &states)
static void log_self_test_exec_status(const char *name, unsigned char status)
static void check_attribute(const dev_config &cfg, dev_state &state, const ata_smart_attribute &attr, const ata_smart_attribute &prev, int attridx, const ata_smart_threshold_entry *thresholds)
static void log_offline_data_coll_status(const char *name, unsigned char status)
static void notify_exit(int)
static void write_all_dev_attrlogs(const dev_config_vector &configs, dev_state_vector &states)
int main(int argc, char **argv)
static int ReadOrMakeConfigEntries(dev_config_vector &conf_entries, smart_device_list &scanned_devs)
static void report_self_test_log_changes(const dev_config &cfg, dev_state &state, int errcnt, uint64_t hour)
static void write_dev_state_line(FILE *f, const char *name, uint64_t val)
static time_t dosleep(time_t wakeuptime, const dev_config_vector &configs, dev_state_vector &states, bool &sigwakeup)
static void notify_extend_timeout()
static void check_pending(const dev_config &cfg, dev_state &state, unsigned char id, bool increase_only, const ata_smart_values &smartval, int mailtype, const char *msg)
static void PrintTestSchedule(const dev_config_vector &configs, dev_state_vector &states, const smart_device_list &devices)
static bool check_abs_path(char option, const std::string &path)
static bool register_device(dev_config &cfg, dev_state &state, smart_device_auto_ptr &dev, const dev_config_vector *prev_cfgs)
static void MailWarning(const dev_config &cfg, dev_state &state, int which, const char *fmt,...) __attribute_format_printf(4
static void init_disable_standby_check(const dev_config_vector &configs)
static void notify_init()
static void install_signal_handlers()
static void capabilities_drop_now()
static void PrintValidArgs(char opt)
const char * smartd_cpp_cvsid
static int NVMeCheckDevice(const dev_config &cfg, dev_state &state, nvme_device *nvmedev, bool firstpass, bool allow_selftests)
static void notify_check(int)
static std::string attrlog_path_prefix
static bool WaitForPidFile()
static void notify_wait(time_t, int)
void checksumwarning(const char *string)
static volatile int caughtsigEXIT
static int ParseConfigFile(dev_config_vector &conf_entries, smart_devtype_list &scan_types)
static uint64_t le128_to_uint64(const unsigned char(&val)[16])
void(* signal_handler_type)(int)
static void write_scsi_attrlog(FILE *f, const dev_state &state)
vsnprintf(buf, sizeof(buf), fmt, ap)
static int standby_disable_state
static void notify_msg(const char *)
static void write_nvme_attrlog(FILE *f, const dev_state &state)
static int SCSICheckDevice(const dev_config &cfg, dev_state &state, scsi_device *scsidev, bool allow_selftests)
static int ParseConfigLine(dev_config_vector &conf_entries, dev_config &default_conf, smart_devtype_list &scan_types, int lineno, char *line)
static const char * GetValidArgList(char opt)
static const char test_type_chars[]
static void write_ata_attrlog(FILE *f, const dev_state &state)
static bool write_dev_attrlog(const char *path, const dev_state &state)
static void CheckDevicesOnce(const dev_config_vector &configs, dev_state_vector &states, smart_device_list &devices, bool firstpass, bool allow_selftests)
static const char * configfile
static const char *const configfile_stdin
static const char * fmt_temp(unsigned char x, char(&buf)[20])
static void write_all_dev_states(const dev_config_vector &configs, dev_state_vector &states, bool write_always=true)
static void static bool notify_post_init()
static void uint64_to_le128(unsigned char(&destval)[16], uint64_t srcval)
static bool check_pending_id(const dev_config &cfg, const dev_state &state, unsigned char id, const char *msg)
static bool not_allowed_in_filename(char c)
static int SCSIDeviceScan(dev_config &cfg, dev_state &state, scsi_device *scsidev, const dev_config_vector *prev_cfgs)
static void capabilities_log_error_hint()
static char next_scheduled_test(const dev_config &cfg, dev_state &state, time_t usetime=0)
static void CheckTemperature(const dev_config &cfg, dev_state &state, unsigned char currtemp, unsigned char triptemp)
static int parse_options(int argc, char **argv)
static unsigned char debugmode
static bool read_dev_state(const char *path, persistent_dev_state &state)
static int DoATASelfTest(const dev_config &cfg, dev_state &state, ata_device *device, char testtype)
static void printoutvaliddirectiveargs(int priority, char d)
static bool write_pid_file()
static time_t calc_next_wakeuptime(time_t wakeuptime, time_t timenow, int ct)
static std::string pid_file
static bool is_offl_coll_in_progress(unsigned char status)
static void USR1handler(int sig)
static bool open_device(const dev_config &cfg, dev_state &state, smart_device *device, const char *type)
static int ATACheckDevice(const dev_config &cfg, dev_state &state, ata_device *atadev, bool firstpass, bool allow_selftests)
static int check_nvme_self_test_log(uint32_t nsid, const nvme_self_test_log &self_test_log, uint64_t &hour)
static int main_worker(int argc, char **argv)
static bool register_devices(const dev_config_vector &conf_entries, smart_device_list &scanned_devs, dev_config_vector &configs, dev_state_vector &states, smart_device_list &devices)
std::vector< dev_config > dev_config_vector
Container for configuration info for each device.
static void HUPhandler(int sig)
static int read_ata_error_count(ata_device *device, const char *name, firmwarebug_defs firmwarebugs, bool extended)
static constexpr int default_checktime
static int GetInteger(const char *arg, const char *name, const char *token, int lineno, const char *cfgfile, int min, int max, char *suffix=0)
static const int SMARTD_NMAIL
static void PrintOut(int priority, const char *fmt,...) __attribute_format_printf(2
static void log_nvme_self_test_exec_status(const char *name, dev_state &state, bool firstpass, const nvme_self_test_log &self_test_log)
static const unsigned num_test_types
static void format_set_result_msg(std::string &msg, const char *name, bool ok, int set_option=0, bool has_value=false)
static int DoSCSISelfTest(const dev_config &cfg, dev_state &state, scsi_device *device, char testtype)
static void set_signal_if_not_ignored(int sig, signal_handler_type handler)
static int ATADeviceScan(dev_config &cfg, dev_state &state, ata_device *atadev, const dev_config_vector *prev_cfgs)
std::vector< dev_state > dev_state_vector
Container for state info for each device.
void pout(const char *fmt,...)
static bool is_self_test_in_progress(unsigned char status)
static void finish_device_scan(dev_config &cfg, dev_state &state)
static bool check_nvme_error_log(const dev_config &cfg, dev_state &state, nvme_device *nvmedev, uint64_t newcnt=0)
static bool parse_dev_state_line(const char *line, persistent_dev_state &state)
static const int scsiLogRespLen
static std::string warning_script
static volatile int caughtsigUSR1
static int MakeConfigEntries(const dev_config &base_cfg, dev_config_vector &conf_entries, smart_device_list &scanned_devs, const smart_devtype_list &types)
static int start_nvme_self_test(const dev_config &cfg, dev_state &state, nvme_device *device, char testtype, const nvme_self_test_log &self_test_log)
static int ParseToken(char *&token, dev_config &cfg, smart_devtype_list &scan_types)
static bool sanitize_dev_idinfo(std::string &s)
static volatile int caughtsigHUP
unsigned short words088_255[168]
unsigned char serial_no[20]
unsigned short int ata_error_count
unsigned char error_log_pointer
unsigned short error_log_index
unsigned short device_error_count
struct ata_smart_log_entry entry[255]
unsigned char mostrecenttest
struct ata_smart_selftestlog_struct selftest_struct[21]
struct ata_smart_threshold_entry thres_entries[NUMBER_ATA_SMART_ATTRIBUTES]
unsigned char self_test_exec_status
unsigned char offline_data_collection_capability
unsigned char offline_data_collection_status
struct ata_smart_attribute vendor_attributes[NUMBER_ATA_SMART_ATTRIBUTES]
Configuration data for a device.
ata_vendor_attr_defs attribute_defs
unsigned short sct_erc_readtime
std::string dev_idinfo_bc
attribute_flags monitor_attr_flags
unsigned nvme_err_log_max_entries
unsigned test_offset_factor
firmwarebug_defs firmwarebugs
unsigned char offl_pending_id
unsigned short sct_erc_writetime
unsigned char curr_pending_id
regular_expression test_regex
Runtime state data for a device.
void update_persistent_state()
Persistent state data for a device.
scsi_nonmedium_error_t scsi_nonmedium_error
nvme_smart_log nvme_smartval
unsigned char selflogcount
uint64_t nvme_err_log_entries
uint64_t selective_test_last_end
ata_attribute ata_attributes[NUMBER_ATA_SMART_ATTRIBUTES]
uint64_t selective_test_last_start
mailinfo maillog[SMARTD_NMAIL]
time_t scheduled_test_next_check
scsi_error_counter_t scsi_error_counters[3]
std::string info_name
Informal name.
std::string dev_type
Actual device type.
std::string dev_name
Device (path)name.
unsigned short status_field
Non-persistent state data for a device.
ata_smart_values smartval
unsigned char NonMediumErrorPageSupported
unsigned char WriteECounterPageSupported
unsigned char temperature
ata_smart_thresholds_pvt smartthres
unsigned char SuppressReport
unsigned char VerifyECounterPageSupported
unsigned char ReadECounterPageSupported
unsigned char TempPageSupported
unsigned char SmartPageSupported
void FixGlibcTimeZoneBug()
const char * format_char_array(char *str, int strsize, const char *chr, int chrsize)
std::string format_version_info(const char *prog_name, int lines)
void dateandtimezoneepoch(char(&buffer)[DATEANDEPOCHLEN], time_t tval)
const char * format_capacity(char *str, int strsize, uint64_t val, const char *decimal_point)
std::string strprintf(const char *fmt,...)
bool nonempty(const void *data, int size)
const char * packetdevicetype(int type)
struct tm * time_to_tm_local(struct tm *tp, time_t t)
#define __attribute_format_printf(x, y)