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>
82#include "os_win32/daemon_win32.h"
83#define strsignal daemon_strsignal
84#define sleep daemon_sleep
86#define SIGQUIT SIGBREAK
87#define SIGQUIT_KEYNAME "CONTROL-Break"
89#define SIGQUIT_KEYNAME "CONTROL-\\"
103 daemon_signal(sig, handler);
105#elif defined(HAVE_SIGACTION)
108 sa.sa_handler = SIG_DFL;
109 sigaction(sig, (
struct sigaction *)0, &sa);
110 if (sa.sa_handler == SIG_IGN)
113 memset(&sa, 0,
sizeof(sa));
114 sa.sa_handler = handler;
115 sa.sa_flags = SA_RESTART;
116 sigaction(sig, &sa, (
struct sigaction *)0);
118#elif defined(HAVE_SIGSET)
120 if (sigset(sig, handler) == SIG_IGN)
121 sigset(sig, SIG_IGN);
127 if (signal(sig, handler) == SIG_IGN)
128 signal(sig, SIG_IGN);
138#define EXIT_BADCONF 2
139#define EXIT_STARTUP 3
142#define EXIT_READCONF 6
145#define EXIT_BADCODE 10
147#define EXIT_BADDEV 16
150#define EXIT_SIGNAL 254
166#ifdef SMARTMONTOOLS_SAVESTATES
167 = SMARTMONTOOLS_SAVESTATES
173#ifdef SMARTMONTOOLS_ATTRIBUTELOG
174 = SMARTMONTOOLS_ATTRIBUTELOG
190static bool warn_as_user;
191static uid_t warn_uid;
192static gid_t warn_gid;
193static std::string warn_uname, warn_gname;
196static bool warn_as_restr_user;
223static volatile int caughtsigUSR2=0;
234static void PrintOut(
int priority,
const char *
fmt, ...)
237#ifdef HAVE_LIBSYSTEMD
240static bool notify_enabled =
false;
241static bool notify_ready =
false;
245 if (!getenv(
"NOTIFY_SOCKET"))
247 notify_enabled =
true;
255 PrintOut(LOG_CRIT,
"Option -n (--no-fork) is required if 'Type=notify' is set.\n");
267 const char * notify =
"EXTEND_TIMEOUT_USEC=20000000";
269 pout(
"sd_notify(0, \"%s\")\n", notify);
272 sd_notify(0, notify);
275static void notify_msg(
const char * msg,
bool ready =
false)
280 pout(
"sd_notify(0, \"%sSTATUS=%s\")\n", (ready ?
"READY=1\\n" :
""), msg);
283 sd_notifyf(0,
"%sSTATUS=%s", (ready ?
"READY=1\n" :
""), msg);
291 snprintf(msg,
sizeof(msg),
"Checking %d device%s ...",
292 numdev, (numdev != 1 ?
"s" :
""));
296static void notify_wait(time_t wakeuptime,
int numdev)
300 char ts[16] =
"";
struct tm tmbuf;
303 snprintf(msg,
sizeof(msg),
"Next check of %d device%s will start at %s",
304 numdev, (numdev != 1 ?
"s" :
""), ts);
315 case 0: msg =
"Exiting ...";
break;
316 case EXIT_BADCMD: msg =
"Error in command line (see SYSLOG)";
break;
318 case EXIT_READCONF: msg =
"Error in config file (see SYSLOG)";
break;
319 case EXIT_BADDEV: msg =
"Unable to register a device (see SYSLOG)";
break;
320 case EXIT_NODEV: msg =
"No devices to monitor";
break;
321 default: msg =
"Error (see SYSLOG)";
break;
334 if (getenv(
"NOTIFY_SOCKET")) {
335 PrintOut(LOG_CRIT,
"This version of smartd was build without 'Type=notify' support.\n");
371 bool is_set(
int id,
unsigned char flag)
const
372 {
return (0 <
id &&
id < (
int)
sizeof(
m_flags) && (
m_flags[
id] & flag)); }
376 if (0 <
id &&
id < (
int)
sizeof(
m_flags))
592 | ((uint64_t)ta.
raw[3] << 24)
593 | ((uint64_t)ta.
raw[4] << 32)
594 | ((uint64_t)ta.
raw[5] << 40);
608 memset(ta.
raw, 0,
sizeof(ta.
raw));
613 ta.
raw[0] = (
unsigned char) pa.
raw;
614 ta.
raw[1] = (
unsigned char)(pa.
raw >> 8);
615 ta.
raw[2] = (
unsigned char)(pa.
raw >> 16);
616 ta.
raw[3] = (
unsigned char)(pa.
raw >> 24);
617 ta.
raw[4] = (
unsigned char)(pa.
raw >> 32);
618 ta.
raw[5] = (
unsigned char)(pa.
raw >> 40);
630 "|(self-test-errors)"
631 "|(self-test-last-err-hour)"
632 "|(scheduled-test-next-check)"
633 "|(selective-test-last-start)"
634 "|(selective-test-last-end)"
636 "|(mail\\.([0-9]+)\\."
642 "|(ata-smart-attribute\\.([0-9]+)\\."
650 "|(nvme-err-log-entries)"
652 " *= *([0-9]+)[ \n]*$"
655 const int nmatch = 1+25;
659 if (
match[nmatch-1].rm_so < 0)
662 uint64_t val = strtoull(line +
match[nmatch-1].rm_so, (
char **)0, 10);
665 if (
match[++m].rm_so >= 0)
666 state.
tempmin = (
unsigned char)val;
667 else if (
match[++m].rm_so >= 0)
668 state.
tempmax = (
unsigned char)val;
669 else if (
match[++m].rm_so >= 0)
671 else if (
match[++m].rm_so >= 0)
673 else if (
match[++m].rm_so >= 0)
675 else if (
match[++m].rm_so >= 0)
677 else if (
match[++m].rm_so >= 0)
679 else if (
match[++m].rm_so >= 0)
681 else if (
match[m+=2].rm_so >= 0) {
682 int i = atoi(line+
match[m].rm_so);
687 if (
match[m+=2].rm_so >= 0)
689 else if (
match[++m].rm_so >= 0)
691 else if (
match[++m].rm_so >= 0)
696 else if (
match[m+=5+1].rm_so >= 0) {
697 int i = atoi(line+
match[m].rm_so);
700 if (
match[m+=2].rm_so >= 0)
702 else if (
match[++m].rm_so >= 0)
704 else if (
match[++m].rm_so >= 0)
706 else if (
match[++m].rm_so >= 0)
708 else if (
match[++m].rm_so >= 0)
713 else if (
match[m+7].rm_so >= 0)
726 pout(
"Cannot read state file \"%s\"\n", path);
730 setmode(fileno(f), O_TEXT);
734 int good = 0, bad = 0;
736 while (fgets(line,
sizeof(line), f)) {
737 const char *
s = line + strspn(line,
" \t");
738 if (!*
s || *
s ==
'#')
748 pout(
"%s: format error\n", path);
751 pout(
"%s: %d invalid line(s) ignored\n", path, bad);
762 fprintf(f,
"%s = %" PRIu64
"\n", name, val);
768 fprintf(f,
"%s.%d.%s = %" PRIu64
"\n", name1,
id, name2, val);
775 std::string pathbak = path; pathbak +=
'~';
776 unlink(pathbak.c_str());
777 rename(path, pathbak.c_str());
781 pout(
"Cannot create state file \"%s\"\n", path);
785 fprintf(f,
"# smartd state file\n");
830 pout(
"Cannot create attribute log file \"%s\"\n", path);
835 time_t now = time(
nullptr);
837 fprintf(f,
"%d-%02d-%02d %02d:%02d:%02d;",
838 1900+tms->tm_year, 1+tms->tm_mon, tms->tm_mday,
839 tms->tm_hour, tms->tm_min, tms->tm_sec);
844 fprintf(f,
"\t%d;%d;%" PRIu64
";", pa.id, pa.val, pa.raw);
848 const char * pageNames[3] = {
"read",
"write",
"verify"};
849 for (
int k = 0; k < 3; ++k) {
852 fprintf(f,
"\t%s-corr-by-ecc-fast;%" PRIu64
";"
853 "\t%s-corr-by-ecc-delayed;%" PRIu64
";"
854 "\t%s-corr-by-retry;%" PRIu64
";"
855 "\t%s-total-err-corrected;%" PRIu64
";"
856 "\t%s-corr-algorithm-invocations;%" PRIu64
";"
857 "\t%s-gb-processed;%.3f;"
858 "\t%s-total-unc-errors;%" PRIu64
";",
864 pageNames[k], (ecp->
counter[5] / 1000000000.0),
865 pageNames[k], ecp->
counter[6]);
872 fprintf(f,
"\ttemperature;%d;", state.
temperature);
882 bool write_always =
true)
884 for (
unsigned i = 0; i < states.size(); i++) {
895 PrintOut(LOG_INFO,
"Device: %s, state written to %s\n",
904 for (
unsigned i = 0; i < states.size(); i++) {
928static void USR2handler(
int sig)
959static int capabilities_mode ;
963 if (!capabilities_mode)
965 capng_clear(CAPNG_SELECT_BOTH);
966 capng_updatev(CAPNG_ADD, (capng_type_t)(CAPNG_EFFECTIVE|CAPNG_PERMITTED),
967 CAP_SYS_ADMIN, CAP_MKNOD, CAP_SYS_RAWIO, -1);
968 if (warn_as_user && (warn_uid || warn_gid)) {
970 capng_updatev(CAPNG_ADD, (capng_type_t)(CAPNG_EFFECTIVE|CAPNG_PERMITTED),
971 CAP_SETGID, CAP_SETUID, -1);
973 if (capabilities_mode > 1) {
975 capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET,
976 CAP_SETGID, CAP_SETUID, CAP_CHOWN, CAP_FOWNER, CAP_DAC_OVERRIDE, -1);
978 capng_apply(CAPNG_SELECT_BOTH);
983 if (!capabilities_mode)
985 PrintOut(LOG_INFO,
"If mail notification does not work with '--capabilities%s\n",
986 (capabilities_mode == 1 ?
"', try '--capabilities=mail'"
987 :
"=mail', please inform " PACKAGE_BUGREPORT));
1015 void set(
const char * name,
const char * value);
1022 int size = strlen(name) + 1 + strlen(value) + 1;
1023 char * newbuf =
new char[
size];
1024 snprintf(newbuf,
size,
"%s=%s", name, value);
1027 throw std::runtime_error(
"putenv() failed");
1048 static const char *
const whichfail[] = {
1054 "FailedHealthCheck",
1055 "FailedReadSmartData",
1056 "FailedReadSmartErrorLog",
1057 "FailedReadSmartSelfTestLog",
1059 "CurrentPendingSector",
1060 "OfflineUncorrectableSector",
1066 PrintOut(LOG_CRIT,
"Internal error in MailWarning(): which=%d\n", which);
1074 days = nextdays = -1;
1077 days = nextdays = -1;
break;
1079 days = nextdays = 0;
break;
1081 days = nextdays = 1;
break;
1084 nextdays = 1 << ((unsigned)mail->
logged <= 5 ? mail->
logged : 5);
1086 days = ((unsigned)mail->
logged <= 5 ? nextdays >> 1 : nextdays);
1089 PrintOut(LOG_CRIT,
"Internal error in MailWarning(): cfg.emailfreq=%d\n", (
int)cfg.
emailfreq);
1093 time_t now = time(
nullptr);
1098 if (days > 0 && now < mail->lastsent + days * 24 * 3600)
1122 std::replace(address.begin(), address.end(),
',',
' ');
1128 env[0].
set(
"SMARTD_MAILER", executable);
1129 env[1].
set(
"SMARTD_MESSAGE", message);
1131 snprintf(dates,
sizeof(dates),
"%d", mail->
logged);
1132 env[2].
set(
"SMARTD_PREVCNT", dates);
1134 env[3].
set(
"SMARTD_TFIRST", dates);
1136 env[4].
set(
"SMARTD_TFIRSTEPOCH", dates);
1137 env[5].
set(
"SMARTD_FAILTYPE", whichfail[which]);
1138 env[6].
set(
"SMARTD_ADDRESS", address.c_str());
1139 env[7].
set(
"SMARTD_DEVICESTRING", cfg.
name.c_str());
1142 env[8].
set(
"SMARTD_DEVICETYPE",
1144 env[9].
set(
"SMARTD_DEVICE", cfg.
dev_name.c_str());
1149 snprintf(dates,
sizeof(dates),
"%d", nextdays);
1150 env[11].
set(
"SMARTD_NEXTDAYS", dates);
1152 env[12].
set(
"SMARTD_SUBJECT",
"");
1156 executable =
"<mail>";
1157 const char * newadd = (!address.empty()? address.c_str() :
"<nomailer>");
1158 const char * newwarn = (which?
"Warning via" :
"Test of");
1163 snprintf(command,
sizeof(command),
"\"%s\" 2>&1",
warning_script.c_str());
1165 snprintf(command,
sizeof(command),
"%s 2>&1",
warning_script.c_str());
1169 PrintOut(LOG_INFO,
"%s %s to %s%s ...\n",
1170 (which ?
"Sending warning via" :
"Executing test of"), executable, newadd,
1172#ifdef HAVE_POSIX_API
1175 (
unsigned)warn_uid, warn_uname.c_str(),
1176 (
unsigned)warn_gid, warn_gname.c_str() ).c_str() :
1178 warn_as_restr_user ?
" (restricted user)" :
1188#ifdef HAVE_POSIX_API
1195 pfp = popen_as_restr_user(command,
"r", warn_as_restr_user);
1197 pfp = popen(command,
"r");
1203 PrintOut(LOG_CRIT,
"%s %s to %s: failed (fork or pipe failed, or no memory) %s\n",
1204 newwarn, executable, newadd, errno?strerror(errno):
"");
1215 PrintOut(LOG_CRIT,
"%s %s to %s produced unexpected output (%s%d bytes) to STDOUT/STDERR: \n%s\n",
1216 newwarn, executable, newadd, len!=newlen?
"here truncated to ":
"", newlen,
buffer);
1224 PrintOut(LOG_CRIT,
"%s %s to %s: flushed remaining STDOUT/STDERR\n",
1225 newwarn, executable, newadd);
1227 PrintOut(LOG_CRIT,
"%s %s to %s: more than 1 MB STDOUT/STDERR flushed, breaking pipe\n",
1228 newwarn, executable, newadd);
1235#ifdef HAVE_POSIX_API
1241 status = pclose(pfp);
1245 PrintOut(LOG_CRIT,
"%s %s to %s: pclose(3) failed %s\n", newwarn, executable, newadd,
1246 errno?strerror(errno):
"");
1249 if (WIFEXITED(status)) {
1251 int status8 = WEXITSTATUS(status);
1253 PrintOut(LOG_CRIT,
"%s %s to %s: failed (32-bit/8-bit exit status: %d/%d) perhaps caught signal %d [%s]\n",
1254 newwarn, executable, newadd, status, status8, status8-128, strsignal(status8-128));
1256 PrintOut(LOG_CRIT,
"%s %s to %s: failed (32-bit/8-bit exit status: %d/%d)\n",
1257 newwarn, executable, newadd, status, status8);
1261 PrintOut(LOG_INFO,
"%s %s to %s: successful\n", newwarn, executable, newadd);
1264 if (WIFSIGNALED(status))
1265 PrintOut(LOG_INFO,
"%s %s to %s: exited because of uncaught signal %d [%s]\n",
1266 newwarn, executable, newadd, WTERMSIG(status), strsignal(WTERMSIG(status)));
1270 if (WIFSTOPPED(status))
1271 PrintOut(LOG_CRIT,
"%s %s to %s: process STOPPED because it caught signal %d [%s]\n",
1272 newwarn, executable, newadd, WSTOPSIG(status), strsignal(WSTOPSIG(status)));
1301 PrintOut(LOG_INFO,
"Device: %s, %s, warning condition reset after %d email%s\n", cfg.
name.c_str(),
1313static
void vsyslog_lines(
int priority, const
char *
fmt, va_list
ap)
1318 for (
char * p = buf, * q; p && *p; p = q) {
1319 if ((q = strchr(p,
'\n')))
1322 syslog(priority,
"%s\n", p);
1328#define vsyslog_lines vsyslog
1352 vfprintf(f,
fmt,
ap);
1357 openlog(
"smartd", LOG_PID,
facility);
1358 vsyslog_lines(LOG_INFO,
fmt,
ap);
1379 vfprintf(f,
fmt,
ap);
1383 openlog(
"smartd", LOG_PID,
facility);
1384 vsyslog_lines(priority,
fmt,
ap);
1394 pout(
"Warning! %s error: invalid SMART checksum.\n",
string);
1403 int waited, max_wait = 10;
1404 struct stat stat_buf;
1409 for(waited = 0; waited < max_wait; ++waited) {
1410 if (!stat(
pid_file.c_str(), &stat_buf)) {
1434 if ((pid=fork()) < 0) {
1436 PrintOut(LOG_CRIT,
"smartd unable to fork daemon process!\n");
1452 if ((pid=fork()) < 0) {
1454 PrintOut(LOG_CRIT,
"smartd unable to fork daemon process!\n");
1465 int open_max = sysconf(_SC_OPEN_MAX);
1466#ifdef HAVE_CLOSE_RANGE
1467 if (close_range(0, open_max - 1, 0))
1472 for (
int i = 0, failed = 0; i < open_max && failed < 1024; i++)
1473 failed = (!close(i) ? 0 : failed + 1);
1477 int fd = open(
"/dev/null", O_RDWR);
1478 if (!(fd == 0 && dup(fd) == 1 && dup(fd) == 2 && !chdir(
"/"))) {
1479 PrintOut(LOG_CRIT,
"smartd unable to redirect to /dev/null or to chdir to root!\n");
1485 PrintOut(LOG_INFO,
"smartd has fork()ed into background mode. New PID=%d.\n", (
int)getpid());
1492 if (daemon_detach(
"smartd")) {
1493 PrintOut(LOG_CRIT,
"smartd unable to detach from console!\n");
1508 pid_t pid = getpid();
1511 old_umask = umask(0077);
1514 old_umask = umask(0033);
1519 if (!(f && fprintf(f,
"%d\n", (
int)pid) > 0 && f.
close())) {
1520 PrintOut(LOG_CRIT,
"unable to write PID file %s - exiting.\n",
pid_file.c_str());
1523 PrintOut(LOG_INFO,
"file %s written containing PID %d\n",
pid_file.c_str(), (
int)pid);
1538 "Configuration file (%s) Directives (after device name):\n"
1539 " -d TYPE Set the device type: auto, ignore, removable,\n"
1541 " -T TYPE Set the tolerance to one of: normal, permissive\n"
1542 " -o VAL Enable/disable automatic offline tests (on/off)\n"
1543 " -S VAL Enable/disable attribute autosave (on/off)\n"
1544 " -n MODE No check if: never, sleep[,N][,q], standby[,N][,q], idle[,N][,q]\n"
1545 " -H Monitor SMART Health Status, report if failed\n"
1546 " -s REG Do Self-Test at time(s) given by regular expression REG\n"
1547 " -l TYPE Monitor SMART log or self-test status:\n"
1548 " error, selftest, xerror, offlinests[,ns], selfteststs[,ns]\n"
1549 " -l scterc,R,W Set SCT Error Recovery Control\n"
1550 " -e Change device setting: aam,[N|off], apm,[N|off], dsn,[on|off],\n"
1551 " lookahead,[on|off], security-freeze, standby,[N|off], wcache,[on|off]\n"
1552 " -f Monitor 'Usage' Attributes, report failures\n"
1553 " -m ADD Send email warning to address ADD\n"
1554 " -M TYPE Modify email warning behavior (see man page)\n"
1555 " -p Report changes in 'Prefailure' Attributes\n"
1556 " -u Report changes in 'Usage' Attributes\n"
1557 " -t Equivalent to -p and -u Directives\n"
1558 " -r ID Also report Raw values of Attribute ID with -p, -u or -t\n"
1559 " -R ID Track changes in Attribute ID Raw value with -p, -u or -t\n"
1560 " -i ID Ignore Attribute ID for -f Directive\n"
1561 " -I ID Ignore Attribute ID for -p, -u or -t Directive\n"
1562 " -C ID[+] Monitor [increases of] Current Pending Sectors in Attribute ID\n"
1563 " -U ID[+] Monitor [increases of] Offline Uncorrectable Sectors in Attribute ID\n"
1564 " -W D,I,C Monitor Temperature D)ifference, I)nformal limit, C)ritical limit\n"
1565 " -v N,ST Modifies labeling of Attribute N (see man page) \n"
1566 " -P TYPE Drive-specific presets: use, ignore, show, showall\n"
1567 " -a Default: -H -f -t -l error -l selftest -l selfteststs -C 197 -U 198\n"
1568 " -F TYPE Use firmware bug workaround:\n"
1570 " -c i=N Set interval between disk checks to N seconds\n"
1571 " # Comment: text after a hash sign is ignored\n"
1572 " \\ Line continuation character\n"
1573 "Attribute ID is a decimal integer 1 <= ID <= 255\n"
1574 "Use ID = 0 to turn off -C and/or -U Directives\n"
1575 "Example: /dev/sda -a\n",
1577 smi()->get_valid_dev_types_str().c_str(),
1588 return "<PATH_PREFIX>, -";
1590 return "[+]<FILE_NAME>";
1592 return "<FILE_NAME>, -";
1594 return "daemon, local0, local1, local2, local3, local4, local5, local6, local7";
1596 return "nodev[0], errors[,nodev0], nodev[0]startup, never, onecheck, showtests";
1598 return "ioctl[,N], ataioctl[,N], scsiioctl[,N], nvmeioctl[,N]";
1601 return "<FILE_NAME>";
1603 return "<INTEGER_SECONDS>";
1604#ifdef HAVE_POSIX_API
1606 return "<USER>[:<GROUP>], -";
1607#elif defined(_WIN32)
1609 return "restricted, unchanged";
1611#ifdef HAVE_LIBCAP_NG
1613 return "mail, <no_argument>";
1623 PrintOut(LOG_INFO,
"Usage: smartd [options]\n\n");
1624#ifdef SMARTMONTOOLS_ATTRIBUTELOG
1625 PrintOut(LOG_INFO,
" -A PREFIX|-, --attributelog=PREFIX|-\n");
1627 PrintOut(LOG_INFO,
" -A PREFIX, --attributelog=PREFIX\n");
1629 PrintOut(LOG_INFO,
" Log attribute information to {PREFIX}MODEL-SERIAL.TYPE.csv\n");
1630#ifdef SMARTMONTOOLS_ATTRIBUTELOG
1631 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_ATTRIBUTELOG
"MODEL-SERIAL.TYPE.csv]\n");
1634 PrintOut(LOG_INFO,
" -B [+]FILE, --drivedb=[+]FILE\n");
1635 PrintOut(LOG_INFO,
" Read and replace [add] drive database from FILE\n");
1637#ifdef SMARTMONTOOLS_DRIVEDBDIR
1639 PrintOut(LOG_INFO,
" and then %s", get_drivedb_path_default());
1642 PrintOut(LOG_INFO,
" -c NAME|-, --configfile=NAME|-\n");
1643 PrintOut(LOG_INFO,
" Read configuration file NAME or stdin\n");
1645#ifdef HAVE_LIBCAP_NG
1646 PrintOut(LOG_INFO,
" -C, --capabilities[=mail]\n");
1647 PrintOut(LOG_INFO,
" Drop unneeded Linux process capabilities.\n"
1648 " Warning: Mail notification may not work when used.\n\n");
1650 PrintOut(LOG_INFO,
" -d, --debug\n");
1651 PrintOut(LOG_INFO,
" Start smartd in debug mode\n\n");
1652 PrintOut(LOG_INFO,
" -D, --showdirectives\n");
1653 PrintOut(LOG_INFO,
" Print the configuration file Directives and exit\n\n");
1654 PrintOut(LOG_INFO,
" -h, --help, --usage\n");
1655 PrintOut(LOG_INFO,
" Display this help and exit\n\n");
1656 PrintOut(LOG_INFO,
" -i N, --interval=N\n");
1657 PrintOut(LOG_INFO,
" Set interval between disk checks to N seconds, where N >= 10\n\n");
1658 PrintOut(LOG_INFO,
" -l local[0-7], --logfacility=local[0-7]\n");
1660 PrintOut(LOG_INFO,
" Use syslog facility local0 - local7 or daemon [default]\n\n");
1662 PrintOut(LOG_INFO,
" Log to \"./smartd.log\", stdout, stderr [default is event log]\n\n");
1665 PrintOut(LOG_INFO,
" -n, --no-fork\n");
1666 PrintOut(LOG_INFO,
" Do not fork into background\n");
1667#ifdef HAVE_LIBSYSTEMD
1668 PrintOut(LOG_INFO,
" (systemd 'Type=notify' is assumed if $NOTIFY_SOCKET is set)\n");
1672 PrintOut(LOG_INFO,
" -p NAME, --pidfile=NAME\n");
1673 PrintOut(LOG_INFO,
" Write PID file NAME\n\n");
1674 PrintOut(LOG_INFO,
" -q WHEN, --quit=WHEN\n");
1676 PrintOut(LOG_INFO,
" -r, --report=TYPE\n");
1678#ifdef SMARTMONTOOLS_SAVESTATES
1679 PrintOut(LOG_INFO,
" -s PREFIX|-, --savestates=PREFIX|-\n");
1681 PrintOut(LOG_INFO,
" -s PREFIX, --savestates=PREFIX\n");
1683 PrintOut(LOG_INFO,
" Save disk states to {PREFIX}MODEL-SERIAL.TYPE.state\n");
1684#ifdef SMARTMONTOOLS_SAVESTATES
1685 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_SAVESTATES
"MODEL-SERIAL.TYPE.state]\n");
1688 PrintOut(LOG_INFO,
" -w NAME, --warnexec=NAME\n");
1689 PrintOut(LOG_INFO,
" Run executable NAME on warnings\n");
1691 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_SMARTDSCRIPTDIR
"/smartd_warning.sh]\n\n");
1695#ifdef HAVE_POSIX_API
1696 PrintOut(LOG_INFO,
" -u USER[:GROUP], --warn-as-user=USER[:GROUP]\n");
1697 PrintOut(LOG_INFO,
" Run warning script as non-privileged USER\n\n");
1698#elif defined(_WIN32)
1699 PrintOut(LOG_INFO,
" -u MODE, --warn-as-user=MODE\n");
1704 PrintOut(LOG_INFO,
" Running as windows service (see man page), install with:\n");
1705 PrintOut(LOG_INFO,
" smartd install [options]\n");
1706 PrintOut(LOG_INFO,
" Remove service with:\n");
1707 PrintOut(LOG_INFO,
" smartd remove\n\n");
1709 PrintOut(LOG_INFO,
" -V, --version, --license, --copyright\n");
1710 PrintOut(LOG_INFO,
" Print License, Copyright, and version information\n");
1715 if (!device->
close()){
1726 bool changed =
false;
1727 for (
unsigned i = 0; i <
s.size(); i++) {
1731 if ((
' ' <= c && c <=
'~') && !(i == 0 && c ==
'~'))
1742 return !( (
'0' <= c && c <=
'9')
1743 || (
'A' <= c && c <=
'Z')
1744 || (
'a' <= c && c <=
'z'));
1755 PrintOut(LOG_INFO,
"Device: %s, Read Summary SMART Error Log failed\n",name);
1763 PrintOut(LOG_INFO,
"Device: %s, Read Extended Comprehensive SMART Error Log failed\n",name);
1779 PrintOut(LOG_INFO,
"Device: %s, Read SMART Self Test Log Failed\n",name);
1788 int errcnt = 0, hours = 0;
1789 for (
int i = 20; i >= 0; i--) {
1795 int status =
entry.selfteststatus >> 4;
1796 if (status == 0x0 && (
entry.selftestnumber & 0x7f) == 0x02)
1800 if (0x3 <= status && status <= 0x8) {
1805 hours =
entry.timestamp;
1809 return ((hours << 8) | errcnt);
1812#define SELFTEST_ERRORCOUNT(x) (x & 0xff)
1813#define SELFTEST_ERRORHOURS(x) ((x >> 8) & 0xffff)
1818 return ((status & 0x7f) == 0x03);
1824 return ((status >> 4) == 0xf);
1831 switch (status & 0x7f) {
1832 case 0x00: msg =
"was never started";
break;
1833 case 0x02: msg =
"was completed without error";
break;
1834 case 0x03: msg =
"is in progress";
break;
1835 case 0x04: msg =
"was suspended by an interrupting command from host";
break;
1836 case 0x05: msg =
"was aborted by an interrupting command from host";
break;
1837 case 0x06: msg =
"was aborted by the device with a fatal error";
break;
1838 default: msg =
nullptr;
1842 PrintOut(((status & 0x7f) == 0x06 ? LOG_CRIT : LOG_INFO),
1843 "Device: %s, offline data collection %s%s\n", name, msg,
1844 ((status & 0x80) ?
" (auto:on)" :
""));
1846 PrintOut(LOG_INFO,
"Device: %s, unknown offline data collection status 0x%02x\n",
1854 switch (status >> 4) {
1855 case 0x0: msg =
"completed without error";
break;
1856 case 0x1: msg =
"was aborted by the host";
break;
1857 case 0x2: msg =
"was interrupted by the host with a reset";
break;
1858 case 0x3: msg =
"could not complete due to a fatal or unknown error";
break;
1859 case 0x4: msg =
"completed with error (unknown test element)";
break;
1860 case 0x5: msg =
"completed with error (electrical test element)";
break;
1861 case 0x6: msg =
"completed with error (servo/seek test element)";
break;
1862 case 0x7: msg =
"completed with error (read test element)";
break;
1863 case 0x8: msg =
"completed with error (handling damage?)";
break;
1864 default: msg =
nullptr;
1868 PrintOut(((status >> 4) >= 0x4 ? LOG_CRIT : LOG_INFO),
1869 "Device: %s, previous self-test %s\n", name, msg);
1870 else if ((status >> 4) == 0xf)
1871 PrintOut(LOG_INFO,
"Device: %s, self-test in progress, %u0%% remaining\n",
1872 name, status & 0x0f);
1874 PrintOut(LOG_INFO,
"Device: %s, unknown self-test status 0x%02x\n",
1880 unsigned char id,
const char * msg)
1885 PrintOut(LOG_INFO,
"Device: %s, can't monitor %s count - no Attribute %d\n",
1886 cfg.
name.c_str(), msg,
id);
1894 PrintOut(LOG_INFO,
"Device: %s, ignoring %s count - bogus Attribute %d value %" PRIu64
" (0x%" PRIx64
")\n",
1895 cfg.
name.c_str(), msg,
id, rawval, rawval);
1921 int set_option = 0,
bool has_value =
false)
1928 else if (set_option < 0)
1932 else if (set_option > 0)
1942 for (
const auto & prev_cfg : prev_cfgs) {
1943 if (!prev_cfg.id_is_unique)
1948 PrintOut(LOG_INFO,
"Device: %s, same identity as %s, ignored\n",
1949 cfg.
dev_name.c_str(), prev_cfg.dev_name.c_str());
1965 const char *name = cfg.
name.c_str();
1974 PrintOut(LOG_INFO,
"Device: %s, not ATA, no IDENTIFY DEVICE Structure\n",name);
1976 PrintOut(LOG_INFO,
"Device: %s, packet devices [this device %s] not SMART capable\n",
1983 char model[40+1], serial[20+1], firmware[8+1];
1993 char wwn[64]; wwn[0] = 0;
1994 unsigned oui = 0; uint64_t unique_id = 0;
1997 snprintf(wwn,
sizeof(wwn),
"WWN:%x-%06x-%09" PRIx64
", ", naa, oui, unique_id);
2018 PrintOut(LOG_INFO,
"Device: %s, smartd database not searched (Directive: -P ignore).\n", name);
2021 std::string dbversion;
2025 PrintOut(LOG_INFO,
"Device: %s, not found in smartd database%s%s.\n", name,
2026 (!dbversion.empty() ?
" " :
""), (!dbversion.empty() ? dbversion.c_str() :
""));
2028 PrintOut(LOG_INFO,
"Device: %s, found in smartd database%s%s%s%s\n",
2029 name, (!dbversion.empty() ?
" " :
""), (!dbversion.empty() ? dbversion.c_str() :
""),
2038 bool locked = ((word128 & 0x0007) == 0x0007);
2040 PrintOut(LOG_INFO,
"Device: %s, ATA Security is **LOCKED**\n", name);
2052 PrintOut(LOG_INFO,
"Device %s: presets are:\n", name);
2064 PrintOut(LOG_INFO,
"Device: %s, lacks SMART capability\n",name);
2067 PrintOut(LOG_INFO,
"Device: %s, ATA IDENTIFY DEVICE words 82-83 don't specify if SMART capable.\n",name);
2071 PrintOut(LOG_INFO,
"Device: %s, proceeding since '-T permissive' Directive given.\n",name);
2074 PrintOut(LOG_INFO,
"Device: %s, to proceed anyway, use '-T permissive' Directive.\n",name);
2082 PrintOut(LOG_INFO,
"Device: %s, could not enable SMART capability\n",name);
2086 PrintOut(LOG_INFO,
"Device: %s, to proceed anyway, use '-T permissive' Directive.\n", name);
2090 PrintOut(LOG_INFO,
"Device: %s, proceeding since '-T permissive' Directive given.\n", name);
2093 PrintOut(LOG_INFO,
"Device: %s, proceeding since SMART is already enabled\n", name);
2100 PrintOut(LOG_INFO,
"Device: %s, could not disable SMART Attribute Autosave.\n",name);
2102 PrintOut(LOG_INFO,
"Device: %s, disabled SMART Attribute Autosave.\n",name);
2108 PrintOut(LOG_INFO,
"Device: %s, could not enable SMART Attribute Autosave.\n",name);
2110 PrintOut(LOG_INFO,
"Device: %s, enabled SMART Attribute Autosave.\n",name);
2115 PrintOut(LOG_INFO,
"Device: %s, not capable of SMART Health Status check\n",name);
2126 bool smart_val_ok =
false;
2135 PrintOut(LOG_INFO,
"Device: %s, Read SMART Values failed\n", name);
2141 smart_val_ok =
true;
2143 PrintOut(LOG_INFO,
"Device: %s, Read SMART Thresholds failed%s\n",
2144 name, (cfg.
usagefailed ?
", ignoring -f Directive" :
""));
2155 "Current_Pending_Sector"))
2160 "Offline_Uncorrectable"))
2165 PrintOut(LOG_INFO,
"Device: %s, can't monitor Temperature, ignoring -W %d,%d,%d\n",
2171 for (
int id = 1;
id <= 255;
id++) {
2179 PrintOut(LOG_INFO,
"Device: %s, no Attribute %d, ignoring -%c %d%s\n", name,
id, opt,
id, excl);
2182 if (!((prefail && cfg.
prefail) || (!prefail && cfg.
usage)))
2183 PrintOut(LOG_INFO,
"Device: %s, not monitoring %s Attributes, ignoring -%c %d%s\n", name,
2184 (prefail ?
"Prefailure" :
"Usage"), opt,
id, excl);
2195 PrintOut(LOG_INFO,
"Device: %s, could not %s SMART Automatic Offline Testing.\n",name, what);
2199 PrintOut(LOG_INFO,
"Device: %s, SMART Automatic Offline Testing unsupported...\n",name);
2202 PrintOut(LOG_INFO,
"Device: %s, %s SMART Automatic Offline Testing failed.\n", name, what);
2204 PrintOut(LOG_INFO,
"Device: %s, %sd SMART Automatic Offline Testing.\n", name, what);
2210 bool smart_logdir_ok =
false, gp_logdir_ok =
false;
2216 smart_logdir_ok =
true;
2221 gp_logdir_ok =
true;
2231 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test Log, ignoring -l selftest (override with -T permissive)\n", name);
2235 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test Log, ignoring -l selftest\n", name);
2251 PrintOut(LOG_INFO,
"Device: %s, no SMART Error Log, ignoring -l error (override with -T permissive)\n", name);
2255 PrintOut(LOG_INFO,
"Device: %s, no SMART Error Log, ignoring -l error\n", name);
2266 PrintOut(LOG_INFO,
"Device: %s, no Extended Comprehensive SMART Error Log, ignoring -l xerror (override with -T permissive)\n",
2271 PrintOut(LOG_INFO,
"Device: %s, no Extended Comprehensive SMART Error Log, ignoring -l xerror\n", name);
2275 PrintOut(LOG_INFO,
"Device: %s, SMART Error Logs report different error counts: %d != %d\n",
2289 PrintOut(LOG_INFO,
"Device: %s, no SMART Offline Data Collection capability, ignoring -l offlinests (override with -T permissive)\n", name);
2291 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test capability, ignoring -l selfteststs (override with -T permissive)\n", name);
2300 if (-1 == powermode) {
2301 PrintOut(LOG_CRIT,
"Device: %s, no ATA CHECK POWER STATUS support, ignoring -n Directive\n", name);
2304 else if (powermode!=0x00 && powermode!=0x01
2305 && powermode!=0x40 && powermode!=0x41
2306 && powermode!=0x80 && powermode!=0x81 && powermode!=0x82 && powermode!=0x83
2307 && powermode!=0xff) {
2308 PrintOut(LOG_CRIT,
"Device: %s, CHECK POWER STATUS returned %d, not ATA compliant, ignoring -n Directive\n",
2350 PrintOut(LOG_INFO,
"Device: %s, ATA settings applied: %s\n", name, msg.c_str());
2355 PrintOut(LOG_INFO,
"Device: %s, no SCT Error Recovery Control support, ignoring -l scterc\n",
2358 PrintOut(LOG_INFO,
"Device: %s, no SCT support if ATA Security is LOCKED, ignoring -l scterc\n",
2362 PrintOut(LOG_INFO,
"Device: %s, set of SCT Error Recovery Control failed\n", name);
2364 PrintOut(LOG_INFO,
"Device: %s, SCT Error Recovery Control set to: Read: %u, Write: %u\n",
2379 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n",name);
2392 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", name, cfg.
state_file.c_str());
2411 int err, req_len, avail_len, version, len;
2412 const char *device = cfg.
name.c_str();
2416 uint8_t vpdBuf[252];
2417 char lu_id[64], serial[256], vendor[40], model[40];
2420 memset(inqBuf, 0, 96);
2427 PrintOut(LOG_INFO,
"Device: %s, Both 36 and 64 byte INQUIRY failed; "
2428 "skip device [err=%d, %d]\n", device, err, err64);
2432 version = (inqBuf[2] & 0x7f);
2434 avail_len = inqBuf[4] + 5;
2435 len = (avail_len < req_len) ? avail_len : req_len;
2437 PrintOut(LOG_INFO,
"Device: %s, INQUIRY response less than 36 bytes; "
2438 "skip device\n", device);
2442 int pdt = inqBuf[0] & 0x1f;
2453 PrintOut(LOG_INFO,
"Device: %s, not a disk like device [PDT=0x%x], "
2454 "skip\n", device, pdt);
2465 if (version >= 0x3) {
2468 vpdBuf,
sizeof(vpdBuf))) {
2475 vpdBuf,
sizeof(vpdBuf))) {
2477 vpdBuf[4 + len] =
'\0';
2492 (
char *)&inqBuf[8], (
char *)&inqBuf[16], (
char *)&inqBuf[32],
2493 (lu_id[0] ?
", lu id: " :
""), (lu_id[0] ? lu_id :
""),
2494 (serial[0] ?
", S/N: " :
""), (serial[0] ? serial :
""),
2495 (si_str[0] ?
", " :
""), (si_str[0] ? si_str :
""));
2515 PrintOut(LOG_INFO,
"Device: %s, NOT READY (e.g. spun down); skip device\n", device);
2517 PrintOut(LOG_INFO,
"Device: %s, NO MEDIUM present; skip device\n", device);
2519 PrintOut(LOG_INFO,
"Device: %s, BECOMING (but not yet) READY; skip device\n", device);
2521 PrintOut(LOG_CRIT,
"Device: %s, failed Test Unit Ready [err=%d]\n", device, err);
2538 "Device: %s, Bad IEC (SMART) mode page, err=%d, skip device\n",
2547 PrintOut(LOG_INFO,
"Device: %s, IE (SMART) not enabled, skip device\n"
2548 "Try 'smartctl -s on %s' to turn on SMART features\n",
2590 uint8_t currenttemp = 0;
2591 uint8_t triptemp = 0;
2594 &asc, &ascq, ¤ttemp, &triptemp)) {
2595 PrintOut(LOG_INFO,
"Device: %s, unexpectedly failed to read SMART values\n", device);
2600 PrintOut(LOG_INFO,
"Device: %s, can't monitor Temperature, ignoring -W %d,%d,%d\n",
2611 PrintOut(LOG_INFO,
"Device: %s, does not support SMART Self-Test Log.\n", device);
2626 PrintOut(LOG_INFO,
"Device: %s, could not disable autosave (set GLTSD bit).\n",device);
2628 PrintOut(LOG_INFO,
"Device: %s, disabled autosave (set GLTSD bit).\n",device);
2634 PrintOut(LOG_INFO,
"Device: %s, could not enable autosave (clear GLTSD bit).\n",device);
2636 PrintOut(LOG_INFO,
"Device: %s, enabled autosave (cleared GLTSD bit).\n",device);
2640 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n", device);
2656 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", device, cfg.
state_file.c_str());
2673 for (
int i = 8; i < 16; i++) {
2675 return ~(uint64_t)0;
2677 uint64_t lo = val[7];
2678 for (
int i = 7-1; i >= 0; i--) {
2679 lo <<= 8; lo += val[i];
2697 uint64_t newcnt = 0)
2701 unsigned want_entries = 64;
2708 if (!read_entries) {
2709 PrintOut(LOG_INFO,
"Device: %s, Read %u entries from Error Information Log failed\n",
2710 cfg.
name.c_str(), want_entries);
2719 int err = 0, ign = 0;
2720 for (
unsigned i = 0; i < read_entries; i++) {
2740 PrintOut(LOG_INFO,
"Device: %s, NVMe error [%u], count %" PRIu64
", status 0x%04x: %s\n",
2745 std::string msg =
strprintf(
"Device: %s, NVMe error count increased from %" PRIu64
" to %" PRIu64
2746 " (%d new, %d ignored, %" PRIu64
" unknown)",
2747 cfg.
name.c_str(), oldcnt, newcnt, err, ign,
2748 (mincnt > oldcnt + 1 ? mincnt - oldcnt - 1 : 0));
2751 PrintOut(LOG_INFO,
"%s\n", msg.c_str());
2754 PrintOut(LOG_CRIT,
"%s\n", msg.c_str());
2766 const char *name = cfg.
name.c_str();
2773 PrintOut(LOG_INFO,
"Device: %s, NVMe Identify Controller failed\n", name);
2779 char model[40+1], serial[20+1], firmware[8+1];
2785 char nsstr[32] =
"", capstr[32] =
"";
2787 if (
nsid != 0xffffffff)
2788 snprintf(nsstr,
sizeof(nsstr),
", NSID:%u",
nsid);
2793 nsstr, (capstr[0] ?
", " :
""), capstr);
2809 PrintOut(LOG_INFO,
"Device: %s, failed to read NVMe SMART/Health Information\n", name);
2817 PrintOut(LOG_INFO,
"Device: %s, no Temperature sensors, ignoring -W %d,%d,%d\n",
2827 PrintOut(LOG_INFO,
"Device: %s, Error Information unavailable, ignoring -l [x]error\n", name);
2842 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n", name);
2854 if (
nsid != 0xffffffff)
2855 snprintf(nsstr,
sizeof(nsstr),
"-n%u",
nsid);
2859 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", name, cfg.
state_file.c_str());
2871 const char * name = cfg.
name.c_str();
2875 MailWarning(cfg, state, 0,
"TEST EMAIL from smartd for device: %s", name);
2890 PrintOut(LOG_INFO,
"Device: %s, is in %s mode, suspending checks\n", name,
"STANDBY (OS)");
2901 if (!device->
open()) {
2904 PrintOut(LOG_INFO,
"Device: %s, open() of %s device failed: %s\n", name, type, device->
get_errmsg());
2905 MailWarning(cfg, state, 9,
"Device: %s, unable to open %s device", name, type);
2908 PrintOut(LOG_INFO,
"Device: %s, removed %s device: %s\n", name, type, device->
get_errmsg());
2912 PrintOut(LOG_INFO,
"Device: %s, %s device still removed: %s\n", name, type, device->
get_errmsg());
2917 PrintOut(LOG_INFO,
"Device: %s, opened %s device\n", name, type);
2922 PrintOut(LOG_INFO,
"Device: %s, reconnected %s device\n", name, type);
2933 const char * name = cfg.
name.c_str();
2937 MailWarning(cfg, state, 8,
"Device: %s, Read SMART Self-Test Log Failed", name);
2951 PrintOut(LOG_CRIT,
"Device: %s, Self-Test Log error count increased from %d to %d\n",
2953 MailWarning(cfg, state, 3,
"Device: %s, Self-Test Log error count increased from %d to %d",
2957 else if (newc > 0 && oldh != newh) {
2965 PrintOut(LOG_CRIT,
"Device: %s, new Self-Test Log error at hour timestamp %d\n",
2967 MailWarning(cfg, state, 3,
"Device: %s, new Self-Test Log error at hour timestamp %d",
2975 PrintOut(LOG_INFO,
"Device: %s, Self-Test Log error count decreased from %d to %d\n",
3012 time_t now = (!usetime ? time(
nullptr) : usetime);
3026 unsigned offsets[max_offsets] = {0, }, limits[max_offsets] = {0, };
3027 unsigned num_offsets = 1;
3029 const char * q = strchr(p,
':');
3033 unsigned offset = 0, limit = 0;
int n1 = -1, n2 = -1, n3 = -1;
3034 sscanf(p,
"%u%n-%n%u%n", &offset, &n1, &n2, &limit, &n3);
3035 if (!(n1 == 3 && (n2 < 0 || (n3 == 3+1+3 && limit > 0))))
3037 offsets[num_offsets] = offset; limits[num_offsets] = limit;
3039 p += (n3 > 0 ? n3 : n1);
3044 time_t testtime = 0;
int testhour = 0;
3049 for (
unsigned i = 0; i < num_offsets; i++) {
3050 unsigned offset = offsets[i], limit = limits[i];
3052 if (0 < limit && limit < delay)
3057 int weekday = (tms->tm_wday ? tms->tm_wday : 7);
3058 for (
int j = 0; j <= maxtest; j++) {
3071 snprintf(pattern,
sizeof(pattern),
"%c/%02d/%02d/%1d/%02d",
3072 test_type_chars[j], tms->tm_mon+1, tms->tm_mday, weekday, tms->tm_hour);
3074 const unsigned len =
sizeof(
"S/01/01/1/01") - 1;
3075 snprintf(pattern + len,
sizeof(pattern) - len,
":%03u", offset);
3077 snprintf(pattern + len + 4,
sizeof(pattern) - len - 4,
"-%03u", limit);
3081 testtype = pattern[0];
3082 testtime = t; testhour = tms->tm_hour;
3096 if ((t += 3600) > now)
3107 if (!usetime && !(testhour == tmnow->tm_hour && testtime + 3600 > now)) {
3109 PrintOut(LOG_INFO,
"Device: %s, old test of type %c not run at %s, starting now.\n",
3110 cfg.
name.c_str(), testtype, datebuf);
3120 unsigned numdev = configs.size();
3125 PrintOut(LOG_INFO,
"\nNext scheduled self tests (at most 5 of each type per device):\n");
3128 time_t now = time(
nullptr);
3135 time_t testtime = now + seconds;
3136 for (
unsigned i = 0; i < numdev; i++) {
3146 PrintOut(LOG_INFO,
"Device: %s, will do test %d of type %c at %s\n", cfg.
name.c_str(),
3155 PrintOut(LOG_INFO,
"\nTotals [%s - %s]:\n", datenow, date);
3156 for (
unsigned i = 0; i < numdev; i++) {
3158 bool scsi =
devices.at(i)->is_scsi();
3163 PrintOut(LOG_INFO,
"Device: %s, will do %3d test%s of type %c\n", cfg.
name.c_str(),
3175 const char *testname =
nullptr;
3176 const char *name = cfg.
name.c_str();
3180 PrintOut(LOG_CRIT,
"Device: %s, does not support Self-Tests\n", name);
3185 if (1 == inProgress) {
3186 PrintOut(LOG_INFO,
"Device: %s, skip since Self-Test already in "
3187 "progress.\n", name);
3193 testname =
"Short Self";
3197 testname =
"Long Self";
3203 PrintOut(LOG_CRIT,
"Device: %s, not capable of %c Self-Test\n", name,
3210 PrintOut(LOG_CRIT,
"Device: %s, not capable of %s-Test\n", name,
3219 PrintOut(LOG_CRIT,
"Device: %s, execute %s-Test failed (err: %d)\n", name,
3224 PrintOut(LOG_INFO,
"Device: %s, starting scheduled %s-Test.\n", name, testname);
3233 const char *name = cfg.
name.c_str();
3238 PrintOut(LOG_CRIT,
"Device: %s, not capable of Offline or Self-Testing.\n", name);
3243 int dotest = -1, mode = 0;
3244 const char *testname =
nullptr;
3247 testname=
"Offline Immediate ";
3254 testname=
"Conveyance Self-";
3261 testname=
"Short Self-";
3268 testname=
"Long Self-";
3275 case 'c':
case 'n':
case 'r':
3276 testname =
"Selective Self-";
3292 PrintOut(LOG_CRIT,
"Device: %s, not capable of %sTest\n", name, testname);
3297 if (15==(
data.self_test_exec_status >> 4)) {
3299 PrintOut(LOG_INFO,
"Device: %s, will not skip scheduled %sTest "
3300 "despite unclear Self-Test byte (SAMSUNG Firmware bug).\n", name, testname);
3302 PrintOut(LOG_INFO,
"Device: %s, skip scheduled %sTest; %1d0%% remaining of current Self-Test.\n",
3303 name, testname, (
int)(
data.self_test_exec_status & 0x0f));
3317 PrintOut(LOG_CRIT,
"Device: %s, prepare %sTest failed\n", name, testname);
3321 PrintOut(LOG_INFO,
"Device: %s, %s test span at LBA %" PRIu64
" - %" PRIu64
" (%" PRIu64
" sectors, %u%% - %u%% of disk).\n",
3323 start, end, end - start + 1,
3333 PrintOut(LOG_CRIT,
"Device: %s, execute %sTest failed.\n", name, testname);
3339 if (testtype ==
'O')
3344 PrintOut(LOG_INFO,
"Device: %s, starting scheduled %sTest.\n", name, testname);
3350 unsigned char id,
bool increase_only,
3352 int mailtype,
const char * msg)
3368 if (!(!increase_only || prev_rawval < rawval))
3372 std::string
s =
strprintf(
"Device: %s, %" PRId64
" %s", cfg.
name.c_str(), rawval, msg);
3373 if (prev_rawval > 0 && rawval != prev_rawval)
3374 s +=
strprintf(
" (changed %+" PRId64
")", rawval - prev_rawval);
3382static const char *
fmt_temp(
unsigned char x,
char (& buf)[20])
3386 snprintf(buf,
sizeof(buf),
"%u", x);
3393 if (!(0 < currtemp && currtemp < 255)) {
3394 PrintOut(LOG_INFO,
"Device: %s, failed to read Temperature\n", cfg.
name.c_str());
3399 const char * minchg =
"", * maxchg =
"";
3400 if (currtemp > state.
tempmax) {
3413 PrintOut(LOG_INFO,
"Device: %s, initial Temperature is %d Celsius (Min/Max %s/%u%s)\n",
3416 PrintOut(LOG_INFO,
" [trip Temperature is %d Celsius]\n", (
int)triptemp);
3440 PrintOut(LOG_INFO,
"Device: %s, Temperature changed %+d Celsius to %u Celsius (Min/Max %s%s/%u%s)\n",
3448 PrintOut(LOG_CRIT,
"Device: %s, Temperature %u Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)\n",
3450 MailWarning(cfg, state, 12,
"Device: %s, Temperature %d Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)",
3454 PrintOut(LOG_INFO,
"Device: %s, Temperature %u Celsius reached limit of %u Celsius (Min/Max %s%s/%u%s)\n",
3459 if (currtemp < limit)
3460 reset_warning_mail(cfg, state, 12,
"Temperature %u Celsius dropped below %u Celsius", currtemp, limit);
3480 PrintOut(LOG_CRIT,
"Device: %s, Failed SMART usage Attribute: %d %s.\n", cfg.
name.c_str(), attr.
id, attrname.c_str());
3481 MailWarning(cfg, state, 2,
"Device: %s, Failed SMART usage Attribute: %d %s.", cfg.
name.c_str(), attr.
id, attrname.c_str());
3487 if (!( ( prefail && cfg.
prefail)
3488 || (!prefail && cfg.
usage )))
3496 if (attr.
id != prev.
id) {
3497 PrintOut(LOG_INFO,
"Device: %s, same Attribute has different ID numbers: %d = %d\n",
3498 cfg.
name.c_str(), attr.
id, prev.
id);
3503 bool valchanged =
false;
3510 bool rawchanged =
false;
3518 if (!(valchanged || rawchanged))
3522 std::string currstr, prevstr;
3544 std::string msg =
strprintf(
"Device: %s, SMART %s Attribute: %d %s changed from %s to %s",
3545 cfg.
name.c_str(), (prefail ?
"Prefailure" :
"Usage"), attr.
id,
3547 prevstr.c_str(), currstr.c_str());
3552 PrintOut(LOG_CRIT,
"%s\n", msg.c_str());
3556 PrintOut(LOG_INFO,
"%s\n", msg.c_str());
3563 bool firstpass,
bool allow_selftests)
3568 const char * name = cfg.
name.c_str();
3575 const char * mode = 0;
3576 if (0 <= powermode && powermode < 0xff) {
3581 if (powermode2 > powermode)
3582 PrintOut(LOG_INFO,
"Device: %s, CHECK POWER STATUS spins up disk (0x%02x -> 0x%02x)\n", name, powermode, powermode2);
3583 powermode = powermode2;
3635 mode=
"ACTIVE or IDLE";
3639 PrintOut(LOG_CRIT,
"Device: %s, CHECK POWER STATUS returned %d, not ATA compliant, ignoring -n Directive\n",
3652 PrintOut(LOG_INFO,
"Device: %s, is in %s mode, suspending checks\n", name, mode);
3659 PrintOut(LOG_INFO,
"Device: %s, %s mode ignored due to reached limit of skipped checks (%d check%s skipped)\n",
3666 PrintOut(LOG_INFO,
"Device: %s, is back in %s mode, resuming checks (%d check%s skipped)\n",
3677 PrintOut(LOG_INFO,
"Device: %s, not capable of SMART self-check\n",name);
3678 MailWarning(cfg, state, 5,
"Device: %s, not capable of SMART self-check", name);
3681 else if (status==1){
3682 PrintOut(LOG_CRIT,
"Device: %s, FAILED SMART self-check. BACK UP DATA NOW!\n", name);
3683 MailWarning(cfg, state, 1,
"Device: %s, FAILED SMART self-check. BACK UP DATA NOW!", name);
3697 PrintOut(LOG_CRIT,
"Device: %s, failed to read SMART Attribute Data\n", name);
3698 MailWarning(cfg, state, 6,
"Device: %s, failed to read SMART Attribute Data", name);
3708 :
"Total unreadable (pending) sectors" ));
3713 :
"Total offline uncorrectable sectors"));
3761 int errcnt1 = -1, errcnt2 = -1;
3768 int newc = (errcnt1 >= errcnt2 ? errcnt1 : errcnt2);
3773 MailWarning(cfg, state, 7,
"Device: %s, Read SMART Error Log Failed", name);
3778 PrintOut(LOG_CRIT,
"Device: %s, ATA error count increased from %d to %d\n",
3780 MailWarning(cfg, state, 4,
"Device: %s, ATA error count increased from %d to %d",
3808 const char * name = cfg.
name.c_str();
3810 uint8_t asc = 0, ascq = 0;
3811 uint8_t currenttemp = 0, triptemp = 0;
3814 &asc, &ascq, ¤ttemp, &triptemp)) {
3815 PrintOut(LOG_INFO,
"Device: %s, failed to read SMART values\n",
3817 MailWarning(cfg, state, 6,
"Device: %s, failed to read SMART values", name);
3826 PrintOut(LOG_CRIT,
"Device: %s, SMART Failure: %s\n", name, cp);
3827 MailWarning(cfg, state, 1,
"Device: %s, SMART Failure: %s", name, cp);
3828 }
else if (asc == 4 && ascq == 9) {
3829 PrintOut(LOG_INFO,
"Device: %s, self-test in progress\n", name);
3831 PrintOut(LOG_INFO,
"Device: %s, non-SMART asc,ascq: %d,%d\n",
3832 name, (
int)asc, (
int)ascq);
3834 PrintOut(LOG_INFO,
"Device: %s, SMART health: passed\n", name);
3890 const char * name = cfg.
name.c_str();
3896 PrintOut(LOG_INFO,
"Device: %s, failed to read NVMe SMART/Health Information\n", name);
3897 MailWarning(cfg, state, 6,
"Device: %s, failed to read NVMe SMART/Health Information", name);
3906 static const char *
const wnames[] =
3907 {
"LowSpare",
"Temperature",
"Reliability",
"R/O",
"VolMemBackup"};
3909 for (
unsigned b = 0, cnt = 0;
b < 8 ;
b++) {
3910 if (!(
w & (1 <<
b)))
3915 msg +=
"...";
break;
3917 if (
b >=
sizeof(wnames)/
sizeof(wnames[0])) {
3918 msg +=
"*Unknown*";
break;
3923 PrintOut(LOG_CRIT,
"Device: %s, Critical Warning (0x%02x): %s\n", name,
w, msg.c_str());
3924 MailWarning(cfg, state, 1,
"Device: %s, Critical Warning (0x%02x): %s", name,
w, msg.c_str());
3961 bool sts1 =
false, sts2 =
false;
3962 for (
const auto & cfg : configs) {
3963 if (cfg.offlinests_ns)
3965 if (cfg.selfteststs_ns)
3972 if (!
smi()->disable_system_auto_standby(
false)) {
3974 PrintOut(LOG_CRIT,
"System auto standby enable failed: %s\n",
smi()->get_errmsg());
3976 PrintOut(LOG_INFO,
"Disable auto standby not supported, ignoring ',ns' from %s%s%s\n",
3977 (sts1 ?
"-l offlinests,ns" :
""), (sts1 && sts2 ?
" and " :
""), (sts2 ?
"-l selfteststs,ns" :
""));
3978 sts1 = sts2 =
false;
3992 bool running =
false;
3993 for (
unsigned i = 0; i < configs.size() && !running; i++) {
4009 if (!
smi()->disable_system_auto_standby(
false))
4010 PrintOut(LOG_CRIT,
"Self-test(s) completed, system auto standby enable failed: %s\n",
4011 smi()->get_errmsg());
4013 PrintOut(LOG_INFO,
"Self-test(s) completed, system auto standby enabled\n");
4017 else if (!
smi()->disable_system_auto_standby(
true)) {
4019 PrintOut(LOG_INFO,
"Self-test(s) in progress, system auto standby disable rejected: %s\n",
4020 smi()->get_errmsg());
4026 PrintOut(LOG_INFO,
"Self-test(s) in progress, system auto standby disabled\n");
4036 for (
unsigned i = 0; i < configs.size(); i++) {
4041 PrintOut(LOG_INFO,
"Device: %s, skipped (interval=%d)\n", cfg.
name.c_str(),
4082static void ToggleDebugMode()
4085 PrintOut(LOG_INFO,
"Signal USR2 - enabling debug mode\n");
4086 if (!daemon_enable_console(
"smartd [Debug]")) {
4089 PrintOut(LOG_INFO,
"smartd debug mode enabled, PID=%d\n", getpid());
4092 PrintOut(LOG_INFO,
"enable console failed\n");
4095 daemon_disable_console();
4098 PrintOut(LOG_INFO,
"Signal USR2 - debug mode disabled\n");
4107 if (timenow < wakeuptime)
4109 return timenow + ct - (timenow - wakeuptime) % ct;
4116 time_t timenow = time(
nullptr);
4117 unsigned n = configs.size();
4127 for (
unsigned i = 0; i < n; i++) {
4133 if (!wakeuptime || state.
wakeuptime < wakeuptime)
4142 bool no_skip =
false;
4146 if (wakeuptime > timenow + ct) {
4147 PrintOut(LOG_INFO,
"System clock time adjusted to the past. Resetting next wakeup time.\n");
4148 wakeuptime = timenow + ct;
4149 for (
auto & state : states)
4150 state.wakeuptime = 0;
4155 sleep(wakeuptime+addtime-timenow);
4159 if (caughtsigUSR2) {
4165 timenow = time(
nullptr);
4168 if (!addtime && timenow > wakeuptime+60) {
4170 PrintOut(LOG_INFO,
"Sleep time was %d seconds too long, assuming wakeup from standby mode.\n",
4171 (
int)(timenow-wakeuptime));
4173 addtime = timenow-wakeuptime+20;
4175 int nextcheck = ct - addtime % ct;
4176 if (nextcheck <= 20)
4177 addtime += nextcheck;
4183 PrintOut(LOG_INFO,
"Signal USR1 - checking devices now rather than in %d seconds.\n",
4184 wakeuptime-timenow>0?(
int)(wakeuptime-timenow):0);
4186 sigwakeup = no_skip =
true;
4191 for (
auto & state : states)
4192 state.skip = (!no_skip && timenow < state.wakeuptime);
4204 PrintOut(priority,
"never[,N][,q], sleep[,N][,q], standby[,N][,q], idle[,N][,q]");
4207 PrintOut(priority,
"valid_regular_expression");
4210 PrintOut(priority,
"%s",
smi()->get_valid_dev_types_str().c_str());
4213 PrintOut(priority,
"normal, permissive");
4220 PrintOut(priority,
"error, selftest");
4223 PrintOut(priority,
"\"once\", \"always\", \"daily\", \"diminishing\", \"test\", \"exec\"");
4229 PrintOut(priority,
"use, ignore, show, showall");
4235 PrintOut(priority,
"aam,[N|off], apm,[N|off], lookahead,[on|off], dsn,[on|off] "
4236 "security-freeze, standby,[N|off], wcache,[on|off]");
4239 PrintOut(priority,
"i=N, interval=N");
4245static int GetInteger(
const char *arg,
const char *name,
const char *token,
int lineno,
const char *cfgfile,
4246 int min,
int max,
char * suffix = 0)
4250 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s takes integer argument from %d to %d.\n",
4251 cfgfile, lineno, name, token, min, max);
4257 int val = strtol(arg,&endptr,10);
4261 if (!strcmp(endptr, suffix))
4262 endptr += strlen(suffix);
4267 if (!(!*endptr && min <= val && val <= max)) {
4268 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s has argument: %s; needs integer from %d to %d.\n",
4269 cfgfile, lineno, name, token, arg, min, max);
4279static int Get3Integers(
const char *arg,
const char *name,
const char *token,
int lineno,
const char *cfgfile,
4280 unsigned char *val1,
unsigned char *val2,
unsigned char *val3)
4282 unsigned v1 = 0, v2 = 0, v3 = 0;
4283 int n1 = -1, n2 = -1, n3 = -1, len;
4285 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s takes 1-3 integer argument(s) from 0 to 255.\n",
4286 cfgfile, lineno, name, token);
4291 if (!( sscanf(arg,
"%u%n,%u%n,%u%n", &v1, &n1, &v2, &n2, &v3, &n3) >= 1
4292 && (n1 == len || n2 == len || n3 == len) && v1 <= 255 && v2 <= 255 && v3 <= 255)) {
4293 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s has argument: %s; needs 1-3 integer(s) from 0 to 255.\n",
4294 cfgfile, lineno, name, token, arg);
4297 *val1 = (
unsigned char)v1; *val2 = (
unsigned char)v2; *val3 = (
unsigned char)v3;
4305static const char * strtok_dequote(
const char * delimiters)
4307 const char * t = strtok(
nullptr, delimiters);
4308 if (!t || t[0] !=
'"')
4311 static std::string token;
4314 t = strtok(
nullptr, delimiters);
4318 int len = strlen(t);
4319 if (t[len-1] ==
'"') {
4320 token += std::string(t, len-1);
4325 return token.c_str();
4337 const char * name = cfg.
name.c_str();
4339 const char *delim =
" \n\t";
4342 const char *arg = 0;
4349 if (*token!=
'-' || strlen(token)!=2) {
4350 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): unknown Directive: %s\n",
4352 PrintOut(LOG_CRIT,
"Run smartd -D to print a list of valid Directives.\n");
4361 char plus[] =
"+", excl[] =
"!";
4366 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 0, 255, plus)) < 0)
4374 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 0, 255, plus)) < 0)
4382 if (!(arg = strtok(
nullptr, delim))) {
4384 }
else if (!strcmp(arg,
"normal")) {
4389 }
else if (!strcmp(arg,
"permissive")) {
4398 if (!(arg = strtok(
nullptr, delim))) {
4400 }
else if (!strcmp(arg,
"ignore")) {
4402 }
else if (!strcmp(arg,
"removable")) {
4404 }
else if (!strcmp(arg,
"auto")) {
4409 scan_types.push_back(arg);
4414 if (!(arg = strtok(
nullptr, delim)))
4442 if (!(arg = strtok(
nullptr, delim))) {
4444 }
else if (!strcmp(arg,
"selftest")) {
4447 }
else if (!strcmp(arg,
"error")) {
4450 }
else if (!strcmp(arg,
"xerror")) {
4453 }
else if (!strcmp(arg,
"offlinests")) {
4456 }
else if (!strcmp(arg,
"offlinests,ns")) {
4459 }
else if (!strcmp(arg,
"selfteststs")) {
4462 }
else if (!strcmp(arg,
"selfteststs,ns")) {
4465 }
else if (!strncmp(arg,
"scterc,",
sizeof(
"scterc,")-1)) {
4467 unsigned rt = ~0, wt = ~0;
int nc = -1;
4468 sscanf(arg,
"scterc,%u,%u%n", &rt, &wt, &nc);
4469 if (nc == (
int)strlen(arg) && rt <= 999 && wt <= 999) {
4492 if (!(arg = strtok(
nullptr, delim))) {
4494 }
else if (!strcmp(arg,
"on")) {
4496 }
else if (!strcmp(arg,
"off")) {
4504 if (!(arg = strtok(
nullptr, delim)))
4507 char *endptr =
nullptr;
4508 char *next = strchr(
const_cast<char*
>(arg),
',');
4515 if (!strcmp(arg,
"never"))
4517 else if (!strcmp(arg,
"sleep"))
4519 else if (!strcmp(arg,
"standby"))
4521 else if (!strcmp(arg,
"idle"))
4527 if (!badarg && next) {
4533 next = endptr + (*endptr !=
'\0');
4537 if (*next !=
'\0') {
4538 if (!strcmp(
"q", next))
4549 if (!(arg = strtok(
nullptr, delim))) {
4551 }
else if (!strcmp(arg,
"on")) {
4553 }
else if (!strcmp(arg,
"off")) {
4562 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous Test Directive -s %s\n",
4567 if (!(arg = strtok(
nullptr, delim))) {
4574 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): -s argument \"%s\" is INVALID extended regular expression. %s.\n",
4583 "[^]$()*+./:?^[|0-9LSCOncr-]+|"
4584 ":[0-9]{0,2}($|[^0-9])|:[0-9]{4,}|"
4585 ":[0-9]{3}-(000|[0-9]{0,2}($|[^0-9])|[0-9]{4,})"
4588 if (syntax_check.
execute(arg, 1, &range) && 0 <= range.rm_so && range.rm_so < range.rm_eo)
4589 PrintOut(LOG_INFO,
"File %s line %d (drive %s): warning, \"%.*s\" looks odd in "
4590 "extended regular expression \"%s\"\n",
4591 configfile, lineno, name, (
int)(range.rm_eo - range.rm_so), arg + range.rm_so, arg);
4596 if (!(arg = strtok(
nullptr, delim)))
4600 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous Address Directive -m %s\n",
4607 if (!(arg = strtok(
nullptr, delim)))
4609 else if (!strcmp(arg,
"once"))
4611 else if (!strcmp(arg,
"always"))
4613 else if (!strcmp(arg,
"daily"))
4615 else if (!strcmp(arg,
"diminishing"))
4617 else if (!strcmp(arg,
"test"))
4619 else if (!strcmp(arg,
"exec")) {
4623 arg = strtok_dequote(delim);
4624 if (arg && arg[0] ==
'"') {
4625 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive %s 'exec' argument: missing closing quote\n",
4630 arg = strtok(
nullptr, delim);
4633 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive %s 'exec' argument must be followed by executable path.\n",
4639 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous mail Directive -M exec %s\n",
4648 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255)) < 0)
4654 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255)) < 0)
4660 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255, excl)) < 0)
4668 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255, excl)) < 0)
4682 if (!(arg = strtok(
nullptr, delim))) {
4690 if (!(arg = strtok(
nullptr, delim))) {
4692 }
else if (!strcmp(arg,
"use")) {
4694 }
else if (!strcmp(arg,
"ignore")) {
4696 }
else if (!strcmp(arg,
"show")) {
4698 }
else if (!strcmp(arg,
"showall")) {
4707 if (!(arg = strtok(
nullptr, delim))) {
4711 char arg2[16+1];
unsigned uval;
4712 int n1 = -1, n2 = -1, n3 = -1, len = strlen(arg);
4713 if (sscanf(arg,
"%16[^,=]%n%*[,=]%n%u%n", arg2, &n1, &n2, &uval, &n3) >= 1
4714 && (n1 == len || n2 > 0)) {
4715 bool on = (n2 > 0 && !strcmp(arg+n2,
"on"));
4716 bool off = (n2 > 0 && !strcmp(arg+n2,
"off"));
4720 if (!strcmp(arg2,
"aam")) {
4723 else if (uval <= 254)
4728 else if (!strcmp(arg2,
"apm")) {
4731 else if (1 <= uval && uval <= 254)
4736 else if (!strcmp(arg2,
"lookahead")) {
4744 else if (!strcmp(arg,
"security-freeze")) {
4747 else if (!strcmp(arg2,
"standby")) {
4750 else if (uval <= 255)
4755 else if (!strcmp(arg2,
"wcache")) {
4763 else if (!strcmp(arg2,
"dsn")) {
4782 if (!(arg = strtok(
nullptr, delim))) {
4786 int n = 0, nc = -1, len = strlen(arg);
4787 if ( ( sscanf(arg,
"i=%d%n", &n, &nc) == 1
4788 || sscanf(arg,
"interval=%d%n", &n, &nc) == 1)
4789 && nc == len && n >= 10)
4798 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): unknown Directive: %s\n",
4800 PrintOut(LOG_CRIT,
"Run smartd -D to print a list of valid Directives.\n");
4804 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Missing argument to %s Directive\n",
4808 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Invalid argument to %s Directive: %s\n",
4811 if (missingarg || badarg) {
4812 PrintOut(LOG_CRIT,
"Valid arguments to %s Directive are: ", token);
4822#define SCANDIRECTIVE "DEVICESCAN"
4836 const char *delim =
" \n\t";
4839 const char * name = strtok(line, delim);
4840 if (!name || *name ==
'#')
4845 if (!strcmp(
"DEFAULT", name)) {
4853 conf_entries.push_back(default_conf);
4855 dev_config & cfg = (retval ? conf_entries.back() : default_conf);
4862 while (
char * token = strtok(
nullptr, delim)) {
4876 if (retval != -1 && scan_types.size() > 1) {
4877 PrintOut(LOG_CRIT,
"Drive: %s, invalid multiple -d TYPE Directives on line %d of file %s\n",
4893 PrintOut(LOG_INFO,
"Drive: %s, implied '-a' Directive on line %d of file %s\n",
4908 PrintOut(LOG_CRIT,
"Drive: %s, -M Directive(s) on line %d of file %s need -m ADDRESS Directive\n",
4917 PrintOut(LOG_CRIT,
"Drive: %s, -m <nomailer> Directive on line %d of file %s needs -M exec Directive\n",
4942 const int MAXLINELEN = 256;
4944 const int MAXCONTLINE = 1023;
4951 int ret = (errno!=ENOENT ? -3 : -2);
4952 PrintOut(LOG_CRIT,
"%s: Unable to open configuration file %s\n",
4968 if (
ParseConfigLine(conf_entries, default_conf, scan_types, 0, fakeconfig) != -1)
4969 throw std::logic_error(
"Internal error parsing " SCANDIRECTIVE);
4974 setmode(fileno(f), O_TEXT);
4981 int lineno = 1, cont = 0, contlineno = 0;
4982 char line[MAXLINELEN+2];
4983 char fullline[MAXCONTLINE+1];
4986 int len=0,scandevice;
4992 memset(line,0,
sizeof(line));
4995 code=fgets(line, MAXLINELEN+2, f);
5000 scandevice =
ParseConfigLine(conf_entries, default_conf, scan_types, contlineno, fullline);
5018 if (len>MAXLINELEN){
5020 if (line[len-1]==
'\n')
5021 warn=
"(including newline!) ";
5024 PrintOut(LOG_CRIT,
"Error: line %d of file %s %sis more than MAXLINELEN=%d characters.\n",
5025 (
int)contlineno,
configfile,warn,(
int)MAXLINELEN);
5030 if ((comment=strchr(line,
'#'))){
5036 if (cont+len>MAXCONTLINE){
5037 PrintOut(LOG_CRIT,
"Error: continued line %d (actual line %d) of file %s is more than MAXCONTLINE=%d characters.\n",
5038 lineno, (
int)contlineno,
configfile, (
int)MAXCONTLINE);
5043 snprintf(fullline+cont,
sizeof(fullline)-cont,
"%s" ,line);
5047 if ( (lastslash=strrchr(line,
'\\')) && !strtok(lastslash+1,
" \n\t")){
5048 *(fullline+(cont-len)+(lastslash-line))=
' ';
5054 scandevice =
ParseConfigLine(conf_entries, default_conf, scan_types, contlineno, fullline);
5078 PrintOut(LOG_CRIT,
"=======> VALID ARGUMENTS ARE: ");
5080 PrintOut(LOG_CRIT,
"Error constructing argument list for option %c", opt);
5090 if (path.empty() || path[0] ==
'/')
5095 PrintOut(LOG_CRIT,
"=======> INVALID ARGUMENT TO -%c: %s <=======\n\n", option, path.c_str());
5096 PrintOut(LOG_CRIT,
"Error: relative path names are not allowed\n\n");
5107 configfile = SMARTMONTOOLS_SYSCONFDIR
"/smartd.conf";
5108 warning_script = SMARTMONTOOLS_SMARTDSCRIPTDIR
"/smartd_warning.sh";
5111 static std::string configfile_str = exedir +
"/smartd.conf";
5117 static const char shortopts[] =
"c:l:q:dDni:p:r:s:A:B:w:Vh?"
5118#if defined(HAVE_POSIX_API) || defined(_WIN32)
5121#ifdef HAVE_LIBCAP_NG
5126 struct option longopts[] = {
5127 {
"configfile", required_argument, 0,
'c' },
5128 {
"logfacility", required_argument, 0,
'l' },
5129 {
"quit", required_argument, 0,
'q' },
5130 {
"debug", no_argument, 0,
'd' },
5131 {
"showdirectives", no_argument, 0,
'D' },
5132 {
"interval", required_argument, 0,
'i' },
5134 {
"no-fork", no_argument, 0,
'n' },
5136 {
"service", no_argument, 0,
'n' },
5138 {
"pidfile", required_argument, 0,
'p' },
5139 {
"report", required_argument, 0,
'r' },
5140 {
"savestates", required_argument, 0,
's' },
5141 {
"attributelog", required_argument, 0,
'A' },
5142 {
"drivedb", required_argument, 0,
'B' },
5143 {
"warnexec", required_argument, 0,
'w' },
5144 {
"version", no_argument, 0,
'V' },
5145 {
"license", no_argument, 0,
'V' },
5146 {
"copyright", no_argument, 0,
'V' },
5147 {
"help", no_argument, 0,
'h' },
5148 {
"usage", no_argument, 0,
'h' },
5149#if defined(HAVE_POSIX_API) || defined(_WIN32)
5150 {
"warn-as-user", required_argument, 0,
'u' },
5152#ifdef HAVE_LIBCAP_NG
5153 {
"capabilities", optional_argument, 0,
'C' },
5159 bool badarg =
false;
5160 const char * badarg_msg =
nullptr;
5161 bool use_default_db =
true;
5165 while ((optchar = getopt_long(argc, argv, shortopts, longopts,
nullptr)) != -1) {
5174 if (!strcmp(optarg,
"nodev"))
5176 else if (!strcmp(optarg,
"nodev0")) {
5180 else if (!strcmp(optarg,
"nodevstartup"))
5182 else if (!strcmp(optarg,
"nodev0startup")) {
5186 else if (!strcmp(optarg,
"errors"))
5188 else if (!strcmp(optarg,
"errors,nodev0")) {
5192 else if (!strcmp(optarg,
"never"))
5194 else if (!strcmp(optarg,
"onecheck")) {
5198 else if (!strcmp(optarg,
"showtests")) {
5207 if (!strcmp(optarg,
"daemon"))
5209 else if (!strcmp(optarg,
"local0"))
5211 else if (!strcmp(optarg,
"local1"))
5213 else if (!strcmp(optarg,
"local2"))
5215 else if (!strcmp(optarg,
"local3"))
5217 else if (!strcmp(optarg,
"local4"))
5219 else if (!strcmp(optarg,
"local5"))
5221 else if (!strcmp(optarg,
"local6"))
5223 else if (!strcmp(optarg,
"local7"))
5247 lchecktime = strtol(optarg, &tailptr, 10);
5248 if (*tailptr !=
'\0' || lchecktime < 10 || lchecktime > INT_MAX || errno) {
5251 PrintOut(LOG_CRIT,
"======> INVALID INTERVAL: %s <=======\n", optarg);
5252 PrintOut(LOG_CRIT,
"======> INTERVAL MUST BE INTEGER BETWEEN %d AND %d <=======\n", 10, INT_MAX);
5253 PrintOut(LOG_CRIT,
"\nUse smartd -h to get a usage summary\n\n");
5261 int n1 = -1, n2 = -1, len = strlen(optarg);
5262 char s[9+1];
unsigned i = 1;
5263 sscanf(optarg,
"%9[a-z]%n,%u%n",
s, &n1, &i, &n2);
5264 if (!((n1 == len || n2 == len) && 1 <= i && i <= 4)) {
5266 }
else if (!strcmp(
s,
"ioctl")) {
5268 }
else if (!strcmp(
s,
"ataioctl")) {
5270 }
else if (!strcmp(
s,
"scsiioctl")) {
5272 }
else if (!strcmp(
s,
"nvmeioctl")) {
5281 if (strcmp(optarg,
"-"))
5300 const char * path = optarg;
5301 if (*path ==
'+' && path[1])
5304 use_default_db =
false;
5314#ifdef HAVE_POSIX_API
5316 warn_as_user =
false;
5317 if (strcmp(optarg,
"-")) {
5318 warn_uname = warn_gname =
"unknown";
5319 badarg_msg =
parse_ugid(optarg, warn_uid, warn_gid,
5320 warn_uname, warn_gname );
5323 warn_as_user =
true;
5326#elif defined(_WIN32)
5328 if (!strcmp(optarg,
"restricted"))
5329 warn_as_restr_user =
true;
5330 else if (!strcmp(optarg,
"unchanged"))
5331 warn_as_restr_user =
false;
5341#ifdef HAVE_LIBCAP_NG
5345 capabilities_mode = 1;
5346 else if (!strcmp(optarg,
"mail"))
5347 capabilities_mode = 2;
5364 arg = argv[optind-1];
5366 if (arg[1] ==
'-' && optchar !=
'h') {
5368 if (optopt && strchr(shortopts, optopt)) {
5369 PrintOut(LOG_CRIT,
"=======> ARGUMENT REQUIRED FOR OPTION: %s <=======\n",arg+2);
5372 PrintOut(LOG_CRIT,
"=======> UNRECOGNIZED OPTION: %s <=======\n\n",arg+2);
5374 PrintOut(LOG_CRIT,
"\nUse smartd --help to get a usage summary\n\n");
5379 if (strchr(shortopts, optopt)){
5380 PrintOut(LOG_CRIT,
"=======> ARGUMENT REQUIRED FOR OPTION: %c <=======\n",optopt);
5383 PrintOut(LOG_CRIT,
"=======> UNRECOGNIZED OPTION: %c <=======\n\n",optopt);
5385 PrintOut(LOG_CRIT,
"\nUse smartd -h to get a usage summary\n\n");
5393 if (badarg || badarg_msg) {
5399 PrintOut(LOG_CRIT,
"=======> INVALID ARGUMENT TO -%c: %s <======= \n", optchar, optarg);
5401 PrintOut(LOG_CRIT,
"%s\n", badarg_msg);
5404 PrintOut(LOG_CRIT,
"\nUse smartd -h to get a usage summary\n\n");
5410 if (argc > optind) {
5413 PrintOut(LOG_CRIT,
"=======> UNRECOGNIZED ARGUMENT: %s <=======\n\n", argv[optind]);
5414 PrintOut(LOG_CRIT,
"\nUse smartd -h to get a usage summary\n\n");
5422 PrintOut(LOG_CRIT,
"=======> INVALID CHOICE OF OPTIONS: -d and -p <======= \n\n");
5423 PrintOut(LOG_CRIT,
"Error: pid file %s not written in debug (-d) mode\n\n",
pid_file.c_str());
5438 if (warn_as_restr_user && !popen_as_restr_check()) {
5441 PrintOut(LOG_CRIT,
"Option '--warn-as-user=restricted' is not effective if the current user\n");
5442 PrintOut(LOG_CRIT,
"is the local 'SYSTEM' or 'Administrator' account\n\n");
5476 if (!
smi()->scan_smart_devices(devlist, types)) {
5477 PrintOut(LOG_CRIT,
"DEVICESCAN failed: %s\n",
smi()->get_errmsg());
5482 if (devlist.
size() == 0)
5486 while (scanned_devs.
size() < conf_entries.size())
5490 for (
unsigned i = 0; i < devlist.
size(); i++) {
5496 conf_entries.push_back(base_cfg);
5509 return devlist.
size();
5522 conf_entries.clear();
5533 else if (!conf_entries.empty()) {
5538 conf_entries.pop_back();
5549 if (conf_entries.empty())
5550 PrintOut(LOG_CRIT,
"In the system's table of devices NO devices found to scan\n");
5555 return conf_entries.size();
5568 PrintOut(LOG_INFO,
"Device: %s, unable to autodetect device type\n", cfg.
name.c_str());
5570 PrintOut(LOG_INFO,
"Device: %s, unsupported device type '%s'\n", cfg.
name.c_str(), cfg.
dev_type.c_str());
5584 dev.
replace( dev->autodetect_open() );
5587 if (oldinfo.
dev_type != dev->get_dev_type())
5588 PrintOut(LOG_INFO,
"Device: %s, type changed from '%s' to '%s'\n",
5589 cfg.
name.c_str(), oldinfo.
dev_type.c_str(), dev->get_dev_type());
5592 if (!dev->is_open()) {
5594 PrintOut(LOG_INFO,
"Device: %s, open() failed: %s\n", dev->get_info_name(), dev->get_errmsg());
5599 cfg.
name = dev->get_info().info_name;
5600 PrintOut(LOG_INFO,
"Device: %s, opened\n", cfg.
name.c_str());
5603 const char * typemsg;
5607 status =
ATADeviceScan(cfg, state, dev->to_ata(), prev_cfgs);
5610 else if (dev->is_scsi()){
5615 else if (dev->is_nvme()) {
5620 PrintOut(LOG_INFO,
"Device: %s, neither ATA, SCSI nor NVMe device\n", cfg.
name.c_str());
5627 PrintOut(scanning ? LOG_INFO : LOG_CRIT,
5628 "Unable to register %s device %s at line %d of file %s\n",
5631 PrintOut(LOG_INFO,
"Unable to register %s device %s\n",
5632 typemsg, cfg.
name.c_str());
5653 typedef std::map<std::string, std::string> prev_unique_names_map;
5654 prev_unique_names_map prev_unique_names;
5657 for (
unsigned i = 0; i < conf_entries.size(); i++) {
5663 pout(
"Device: %s%s%s%s, unique name: %s\n", cfg.
name.c_str(),
5665 (!cfg.
dev_type.empty() ?
"]" :
""), unique_name.c_str());
5670 PrintOut(LOG_INFO,
"Device: %s%s%s%s, ignored\n", cfg.
name.c_str(),
5672 (!cfg.
dev_type.empty() ?
"]" :
""));
5673 prev_unique_names[unique_name] = cfg.
name;
5680 bool scanning =
false;
5681 if (i < scanned_devs.
size()) {
5682 dev = scanned_devs.
release(i);
5685 prev_unique_names_map::iterator ui = prev_unique_names.find(unique_name);
5686 if (ui != prev_unique_names.end()) {
5687 bool ne = (ui->second != cfg.
name);
5688 PrintOut(LOG_INFO,
"Device: %s, %s%s, ignored\n", dev->get_info_name(),
5689 (ne ?
"same as " :
"duplicate"), (ne ? ui->second.c_str() :
""));
5707 PrintOut(LOG_CRIT,
"Unable to register device %s (no Directive -d removable). Exiting.\n",
5711 PrintOut(LOG_INFO,
"Device: %s, not available\n", cfg.
name.c_str());
5713 prev_unique_names[unique_name] = cfg.
name;
5719 configs.push_back(cfg);
5720 states.push_back(state);
5724 prev_unique_names[unique_name] = cfg.
name;
5729 unsigned factor = 0;
5730 for (
auto & cfg : configs) {
5733 if (!cfg.test_regex.empty())
5734 cfg.test_offset_factor = factor++;
5773 bool firstpass =
true, write_states_always =
true;
5774 time_t wakeuptime = 0;
5786 "Signal HUP - rereading configuration file %s\n":
5787 "\a\nSignal INT - rereading configuration file %s (" SIGQUIT_KEYNAME " quits)\n\n",
5804 if (!(configs.size() ==
devices.size() && configs.size() == states.size()))
5805 throw std::logic_error(
"Invalid result from RegisterDevices");
5811 PrintOut(LOG_INFO,
"Reusing previous configuration\n");
5823 PrintOut((status ? LOG_CRIT : LOG_INFO),
5824 "Unable to monitor any SMART enabled devices. Exiting.\n");
5829 int numata = 0, numscsi = 0;
5830 for (
unsigned i = 0; i <
devices.size(); i++) {
5837 PrintOut(LOG_INFO,
"Monitoring %d ATA/SATA, %d SCSI/SAS and %d NVMe devices\n",
5838 numata, numscsi, (
int)
devices.size() - numata - numscsi);
5851 write_states_always =
true;
5862 write_states_always =
false;
5870 PrintOut(LOG_INFO,
"Started with '-q onecheck' option. All devices successfully checked once.\n"
5871 "smartd is exiting (exit status 0)\n");
5893 wakeuptime = time(
nullptr);
5899 wakeuptime =
dosleep(wakeuptime, configs, states, write_states_always);
5906 PrintOut(LOG_INFO,
"smartd received signal %d: %s\n",
5911 PrintOut(LOG_CRIT,
"smartd received unexpected signal %d: %s\n",
5930 PrintOut(LOG_CRIT,
"Can't unlink PID file %s (%s).\n",
5931 pid_file.c_str(), strerror(errno));
5934 PrintOut((status ? LOG_CRIT : LOG_INFO),
"smartd is exiting (exit status %d)\n", status);
5944static int smartd_main(
int argc,
char **argv)
5952 catch (
const std::bad_alloc & ) {
5954 PrintOut(LOG_CRIT,
"Smartd: Out of memory\n");
5957 catch (
const std::exception & ex) {
5959 PrintOut(LOG_CRIT,
"Smartd: Exception: %s\n", ex.what());
5965 PrintOut(LOG_CRIT,
"Smartd: Internal Error: %d device object(s) left at exit.\n",
5971 PrintOut(LOG_CRIT,
"Please inform " PACKAGE_BUGREPORT
", including output of smartd -V.\n");
5975 daemon_winsvc_exitcode = status;
5983int main(
int argc,
char **argv){
5985 static const daemon_winsvc_options svc_opts = {
5987 "smartd",
"SmartD Service",
5989 "Controls and monitors storage devices using the Self-Monitoring, "
5990 "Analysis and Reporting Technology System (SMART) built into "
5991 "ATA/SATA and SCSI/SAS hard drives and solid-state drives. "
5992 "www.smartmontools.org"
5997 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)
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_read_smart_log(nvme_device *device, nvme_smart_log &smart_log)
unsigned nvme_read_error_log(nvme_device *device, nvme_error_log_page *error_log, unsigned num_entries, bool lpo_sup)
const char * nvme_status_to_info_str(char *buf, size_t bufsize, uint16_t status)
constexpr bool nvme_status_is_error(uint16_t status)
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 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 int SelfTestErrorCount(ata_device *device, const char *name, firmwarebug_defs firmwarebugs)
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 int ParseToken(char *token, dev_config &cfg, smart_devtype_list &scan_types)
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 sighandler(int sig)
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 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 char next_scheduled_test(const dev_config &cfg, dev_state &state, bool scsi, time_t usetime=0)
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 void notify_check(int)
static int NVMeCheckDevice(const dev_config &cfg, dev_state &state, nvme_device *nvmedev)
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
for(char *p=buf, *q;p &&*p;p=q)
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)
vsnprintf(buf, sizeof(buf), fmt, ap)
static int standby_disable_state
static void notify_msg(const char *)
#define SELFTEST_ERRORCOUNT(x)
static int SCSICheckDevice(const dev_config &cfg, dev_state &state, scsi_device *scsidev, bool allow_selftests)
#define SELFTEST_ERRORHOURS(x)
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 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 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 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 void CheckSelfTestLogs(const dev_config &cfg, dev_state &state, int newi)
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 nvme_get_max_temp_kelvin(const nvme_smart_log &smart_log)
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 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)
time_t calc_next_wakeuptime(time_t wakeuptime, time_t timenow, int ct)
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 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
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
unsigned char selflogcount
unsigned short selfloghour
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)