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))
589 | ((uint64_t)ta.
raw[3] << 24)
590 | ((uint64_t)ta.
raw[4] << 32)
591 | ((uint64_t)ta.
raw[5] << 40);
605 memset(ta.
raw, 0,
sizeof(ta.
raw));
610 ta.
raw[0] = (
unsigned char) pa.
raw;
611 ta.
raw[1] = (
unsigned char)(pa.
raw >> 8);
612 ta.
raw[2] = (
unsigned char)(pa.
raw >> 16);
613 ta.
raw[3] = (
unsigned char)(pa.
raw >> 24);
614 ta.
raw[4] = (
unsigned char)(pa.
raw >> 32);
615 ta.
raw[5] = (
unsigned char)(pa.
raw >> 40);
627 "|(self-test-errors)"
628 "|(self-test-last-err-hour)"
629 "|(scheduled-test-next-check)"
630 "|(selective-test-last-start)"
631 "|(selective-test-last-end)"
633 "|(mail\\.([0-9]+)\\."
639 "|(ata-smart-attribute\\.([0-9]+)\\."
647 "|(nvme-err-log-entries)"
649 " *= *([0-9]+)[ \n]*$"
652 const int nmatch = 1+25;
656 if (
match[nmatch-1].rm_so < 0)
659 uint64_t val = strtoull(line +
match[nmatch-1].rm_so, (
char **)0, 10);
662 if (
match[++m].rm_so >= 0)
663 state.
tempmin = (
unsigned char)val;
664 else if (
match[++m].rm_so >= 0)
665 state.
tempmax = (
unsigned char)val;
666 else if (
match[++m].rm_so >= 0)
668 else if (
match[++m].rm_so >= 0)
670 else if (
match[++m].rm_so >= 0)
672 else if (
match[++m].rm_so >= 0)
674 else if (
match[++m].rm_so >= 0)
676 else if (
match[++m].rm_so >= 0)
678 else if (
match[m+=2].rm_so >= 0) {
679 int i = atoi(line+
match[m].rm_so);
684 if (
match[m+=2].rm_so >= 0)
686 else if (
match[++m].rm_so >= 0)
688 else if (
match[++m].rm_so >= 0)
693 else if (
match[m+=5+1].rm_so >= 0) {
694 int i = atoi(line+
match[m].rm_so);
697 if (
match[m+=2].rm_so >= 0)
699 else if (
match[++m].rm_so >= 0)
701 else if (
match[++m].rm_so >= 0)
703 else if (
match[++m].rm_so >= 0)
705 else if (
match[++m].rm_so >= 0)
710 else if (
match[m+7].rm_so >= 0)
723 pout(
"Cannot read state file \"%s\"\n", path);
727 setmode(fileno(f), O_TEXT);
731 int good = 0, bad = 0;
733 while (fgets(line,
sizeof(line), f)) {
734 const char *
s = line + strspn(line,
" \t");
735 if (!*
s || *
s ==
'#')
745 pout(
"%s: format error\n", path);
748 pout(
"%s: %d invalid line(s) ignored\n", path, bad);
759 fprintf(f,
"%s = %" PRIu64
"\n", name, val);
765 fprintf(f,
"%s.%d.%s = %" PRIu64
"\n", name1,
id, name2, val);
772 std::string pathbak = path; pathbak +=
'~';
773 unlink(pathbak.c_str());
774 rename(path, pathbak.c_str());
778 pout(
"Cannot create state file \"%s\"\n", path);
782 fprintf(f,
"# smartd state file\n");
827 pout(
"Cannot create attribute log file \"%s\"\n", path);
832 time_t now = time(
nullptr);
834 fprintf(f,
"%d-%02d-%02d %02d:%02d:%02d;",
835 1900+tms->tm_year, 1+tms->tm_mon, tms->tm_mday,
836 tms->tm_hour, tms->tm_min, tms->tm_sec);
841 fprintf(f,
"\t%d;%d;%" PRIu64
";", pa.id, pa.val, pa.raw);
845 const char * pageNames[3] = {
"read",
"write",
"verify"};
846 for (
int k = 0; k < 3; ++k) {
849 fprintf(f,
"\t%s-corr-by-ecc-fast;%" PRIu64
";"
850 "\t%s-corr-by-ecc-delayed;%" PRIu64
";"
851 "\t%s-corr-by-retry;%" PRIu64
";"
852 "\t%s-total-err-corrected;%" PRIu64
";"
853 "\t%s-corr-algorithm-invocations;%" PRIu64
";"
854 "\t%s-gb-processed;%.3f;"
855 "\t%s-total-unc-errors;%" PRIu64
";",
861 pageNames[k], (ecp->
counter[5] / 1000000000.0),
862 pageNames[k], ecp->
counter[6]);
869 fprintf(f,
"\ttemperature;%d;", state.
temperature);
879 bool write_always =
true)
881 for (
unsigned i = 0; i < states.size(); i++) {
892 PrintOut(LOG_INFO,
"Device: %s, state written to %s\n",
901 for (
unsigned i = 0; i < states.size(); i++) {
925static void USR2handler(
int sig)
956static int capabilities_mode ;
960 if (!capabilities_mode)
962 capng_clear(CAPNG_SELECT_BOTH);
963 capng_updatev(CAPNG_ADD, (capng_type_t)(CAPNG_EFFECTIVE|CAPNG_PERMITTED),
964 CAP_SYS_ADMIN, CAP_MKNOD, CAP_SYS_RAWIO, -1);
965 if (warn_as_user && (warn_uid || warn_gid)) {
967 capng_updatev(CAPNG_ADD, (capng_type_t)(CAPNG_EFFECTIVE|CAPNG_PERMITTED),
968 CAP_SETGID, CAP_SETUID, -1);
970 if (capabilities_mode > 1) {
972 capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET,
973 CAP_SETGID, CAP_SETUID, CAP_CHOWN, CAP_FOWNER, CAP_DAC_OVERRIDE, -1);
975 capng_apply(CAPNG_SELECT_BOTH);
980 if (!capabilities_mode)
982 PrintOut(LOG_INFO,
"If mail notification does not work with '--capabilities%s\n",
983 (capabilities_mode == 1 ?
"', try '--capabilities=mail'"
984 :
"=mail', please inform " PACKAGE_BUGREPORT));
1012 void set(
const char * name,
const char * value);
1019 int size = strlen(name) + 1 + strlen(value) + 1;
1020 char * newbuf =
new char[
size];
1021 snprintf(newbuf,
size,
"%s=%s", name, value);
1024 throw std::runtime_error(
"putenv() failed");
1045 static const char *
const whichfail[] = {
1051 "FailedHealthCheck",
1052 "FailedReadSmartData",
1053 "FailedReadSmartErrorLog",
1054 "FailedReadSmartSelfTestLog",
1056 "CurrentPendingSector",
1057 "OfflineUncorrectableSector",
1063 PrintOut(LOG_CRIT,
"Internal error in MailWarning(): which=%d\n", which);
1071 days = nextdays = -1;
1074 days = nextdays = -1;
break;
1076 days = nextdays = 0;
break;
1078 days = nextdays = 1;
break;
1081 nextdays = 1 << ((unsigned)mail->
logged <= 5 ? mail->
logged : 5);
1083 days = ((unsigned)mail->
logged <= 5 ? nextdays >> 1 : nextdays);
1086 PrintOut(LOG_CRIT,
"Internal error in MailWarning(): cfg.emailfreq=%d\n", (
int)cfg.
emailfreq);
1090 time_t now = time(
nullptr);
1095 if (days > 0 && now < mail->lastsent + days * 24 * 3600)
1119 std::replace(address.begin(), address.end(),
',',
' ');
1125 env[0].
set(
"SMARTD_MAILER", executable);
1126 env[1].
set(
"SMARTD_MESSAGE", message);
1128 snprintf(dates,
sizeof(dates),
"%d", mail->
logged);
1129 env[2].
set(
"SMARTD_PREVCNT", dates);
1131 env[3].
set(
"SMARTD_TFIRST", dates);
1133 env[4].
set(
"SMARTD_TFIRSTEPOCH", dates);
1134 env[5].
set(
"SMARTD_FAILTYPE", whichfail[which]);
1135 env[6].
set(
"SMARTD_ADDRESS", address.c_str());
1136 env[7].
set(
"SMARTD_DEVICESTRING", cfg.
name.c_str());
1139 env[8].
set(
"SMARTD_DEVICETYPE",
1141 env[9].
set(
"SMARTD_DEVICE", cfg.
dev_name.c_str());
1146 snprintf(dates,
sizeof(dates),
"%d", nextdays);
1147 env[11].
set(
"SMARTD_NEXTDAYS", dates);
1149 env[12].
set(
"SMARTD_SUBJECT",
"");
1153 executable =
"<mail>";
1154 const char * newadd = (!address.empty()? address.c_str() :
"<nomailer>");
1155 const char * newwarn = (which?
"Warning via" :
"Test of");
1160 snprintf(command,
sizeof(command),
"\"%s\" 2>&1",
warning_script.c_str());
1162 snprintf(command,
sizeof(command),
"%s 2>&1",
warning_script.c_str());
1166 PrintOut(LOG_INFO,
"%s %s to %s%s ...\n",
1167 (which ?
"Sending warning via" :
"Executing test of"), executable, newadd,
1169#ifdef HAVE_POSIX_API
1172 (
unsigned)warn_uid, warn_uname.c_str(),
1173 (
unsigned)warn_gid, warn_gname.c_str() ).c_str() :
1175 warn_as_restr_user ?
" (restricted user)" :
1185#ifdef HAVE_POSIX_API
1192 pfp = popen_as_restr_user(command,
"r", warn_as_restr_user);
1194 pfp = popen(command,
"r");
1200 PrintOut(LOG_CRIT,
"%s %s to %s: failed (fork or pipe failed, or no memory) %s\n",
1201 newwarn, executable, newadd, errno?strerror(errno):
"");
1212 PrintOut(LOG_CRIT,
"%s %s to %s produced unexpected output (%s%d bytes) to STDOUT/STDERR: \n%s\n",
1213 newwarn, executable, newadd, len!=newlen?
"here truncated to ":
"", newlen,
buffer);
1221 PrintOut(LOG_CRIT,
"%s %s to %s: flushed remaining STDOUT/STDERR\n",
1222 newwarn, executable, newadd);
1224 PrintOut(LOG_CRIT,
"%s %s to %s: more than 1 MB STDOUT/STDERR flushed, breaking pipe\n",
1225 newwarn, executable, newadd);
1232#ifdef HAVE_POSIX_API
1238 status = pclose(pfp);
1242 PrintOut(LOG_CRIT,
"%s %s to %s: pclose(3) failed %s\n", newwarn, executable, newadd,
1243 errno?strerror(errno):
"");
1246 if (WIFEXITED(status)) {
1248 int status8 = WEXITSTATUS(status);
1250 PrintOut(LOG_CRIT,
"%s %s to %s: failed (32-bit/8-bit exit status: %d/%d) perhaps caught signal %d [%s]\n",
1251 newwarn, executable, newadd, status, status8, status8-128, strsignal(status8-128));
1253 PrintOut(LOG_CRIT,
"%s %s to %s: failed (32-bit/8-bit exit status: %d/%d)\n",
1254 newwarn, executable, newadd, status, status8);
1258 PrintOut(LOG_INFO,
"%s %s to %s: successful\n", newwarn, executable, newadd);
1261 if (WIFSIGNALED(status))
1262 PrintOut(LOG_INFO,
"%s %s to %s: exited because of uncaught signal %d [%s]\n",
1263 newwarn, executable, newadd, WTERMSIG(status), strsignal(WTERMSIG(status)));
1267 if (WIFSTOPPED(status))
1268 PrintOut(LOG_CRIT,
"%s %s to %s: process STOPPED because it caught signal %d [%s]\n",
1269 newwarn, executable, newadd, WSTOPSIG(status), strsignal(WSTOPSIG(status)));
1298 PrintOut(LOG_INFO,
"Device: %s, %s, warning condition reset after %d email%s\n", cfg.
name.c_str(),
1310static
void vsyslog_lines(
int priority, const
char *
fmt, va_list
ap)
1315 for (
char * p = buf, * q; p && *p; p = q) {
1316 if ((q = strchr(p,
'\n')))
1319 syslog(priority,
"%s\n", p);
1325#define vsyslog_lines vsyslog
1349 vfprintf(f,
fmt,
ap);
1354 openlog(
"smartd", LOG_PID,
facility);
1355 vsyslog_lines(LOG_INFO,
fmt,
ap);
1376 vfprintf(f,
fmt,
ap);
1380 openlog(
"smartd", LOG_PID,
facility);
1381 vsyslog_lines(priority,
fmt,
ap);
1391 pout(
"Warning! %s error: invalid SMART checksum.\n",
string);
1400 int waited, max_wait = 10;
1401 struct stat stat_buf;
1406 for(waited = 0; waited < max_wait; ++waited) {
1407 if (!stat(
pid_file.c_str(), &stat_buf)) {
1431 if ((pid=fork()) < 0) {
1433 PrintOut(LOG_CRIT,
"smartd unable to fork daemon process!\n");
1449 if ((pid=fork()) < 0) {
1451 PrintOut(LOG_CRIT,
"smartd unable to fork daemon process!\n");
1462 int open_max = sysconf(_SC_OPEN_MAX);
1463#ifdef HAVE_CLOSE_RANGE
1464 if (close_range(0, open_max - 1, 0))
1469 for (
int i = 0, failed = 0; i < open_max && failed < 1024; i++)
1470 failed = (!close(i) ? 0 : failed + 1);
1474 int fd = open(
"/dev/null", O_RDWR);
1475 if (!(fd == 0 && dup(fd) == 1 && dup(fd) == 2 && !chdir(
"/"))) {
1476 PrintOut(LOG_CRIT,
"smartd unable to redirect to /dev/null or to chdir to root!\n");
1482 PrintOut(LOG_INFO,
"smartd has fork()ed into background mode. New PID=%d.\n", (
int)getpid());
1489 if (daemon_detach(
"smartd")) {
1490 PrintOut(LOG_CRIT,
"smartd unable to detach from console!\n");
1505 pid_t pid = getpid();
1508 old_umask = umask(0077);
1511 old_umask = umask(0033);
1516 if (!(f && fprintf(f,
"%d\n", (
int)pid) > 0 && f.
close())) {
1517 PrintOut(LOG_CRIT,
"unable to write PID file %s - exiting.\n",
pid_file.c_str());
1520 PrintOut(LOG_INFO,
"file %s written containing PID %d\n",
pid_file.c_str(), (
int)pid);
1535 "Configuration file (%s) Directives (after device name):\n"
1536 " -d TYPE Set the device type: auto, ignore, removable,\n"
1538 " -T TYPE Set the tolerance to one of: normal, permissive\n"
1539 " -o VAL Enable/disable automatic offline tests (on/off)\n"
1540 " -S VAL Enable/disable attribute autosave (on/off)\n"
1541 " -n MODE No check if: never, sleep[,N][,q], standby[,N][,q], idle[,N][,q]\n"
1542 " -H Monitor SMART Health Status, report if failed\n"
1543 " -s REG Do Self-Test at time(s) given by regular expression REG\n"
1544 " -l TYPE Monitor SMART log or self-test status:\n"
1545 " error, selftest, xerror, offlinests[,ns], selfteststs[,ns]\n"
1546 " -l scterc,R,W Set SCT Error Recovery Control\n"
1547 " -e Change device setting: aam,[N|off], apm,[N|off], dsn,[on|off],\n"
1548 " lookahead,[on|off], security-freeze, standby,[N|off], wcache,[on|off]\n"
1549 " -f Monitor 'Usage' Attributes, report failures\n"
1550 " -m ADD Send email warning to address ADD\n"
1551 " -M TYPE Modify email warning behavior (see man page)\n"
1552 " -p Report changes in 'Prefailure' Attributes\n"
1553 " -u Report changes in 'Usage' Attributes\n"
1554 " -t Equivalent to -p and -u Directives\n"
1555 " -r ID Also report Raw values of Attribute ID with -p, -u or -t\n"
1556 " -R ID Track changes in Attribute ID Raw value with -p, -u or -t\n"
1557 " -i ID Ignore Attribute ID for -f Directive\n"
1558 " -I ID Ignore Attribute ID for -p, -u or -t Directive\n"
1559 " -C ID[+] Monitor [increases of] Current Pending Sectors in Attribute ID\n"
1560 " -U ID[+] Monitor [increases of] Offline Uncorrectable Sectors in Attribute ID\n"
1561 " -W D,I,C Monitor Temperature D)ifference, I)nformal limit, C)ritical limit\n"
1562 " -v N,ST Modifies labeling of Attribute N (see man page) \n"
1563 " -P TYPE Drive-specific presets: use, ignore, show, showall\n"
1564 " -a Default: -H -f -t -l error -l selftest -l selfteststs -C 197 -U 198\n"
1565 " -F TYPE Use firmware bug workaround:\n"
1567 " -c i=N Set interval between disk checks to N seconds\n"
1568 " # Comment: text after a hash sign is ignored\n"
1569 " \\ Line continuation character\n"
1570 "Attribute ID is a decimal integer 1 <= ID <= 255\n"
1571 "Use ID = 0 to turn off -C and/or -U Directives\n"
1572 "Example: /dev/sda -a\n",
1574 smi()->get_valid_dev_types_str().c_str(),
1585 return "<PATH_PREFIX>, -";
1587 return "[+]<FILE_NAME>";
1589 return "<FILE_NAME>, -";
1591 return "daemon, local0, local1, local2, local3, local4, local5, local6, local7";
1593 return "nodev[0], errors[,nodev0], nodev[0]startup, never, onecheck, showtests";
1595 return "ioctl[,N], ataioctl[,N], scsiioctl[,N], nvmeioctl[,N]";
1598 return "<FILE_NAME>";
1600 return "<INTEGER_SECONDS>";
1601#ifdef HAVE_POSIX_API
1603 return "<USER>[:<GROUP>], -";
1604#elif defined(_WIN32)
1606 return "restricted, unchanged";
1608#ifdef HAVE_LIBCAP_NG
1610 return "mail, <no_argument>";
1620 PrintOut(LOG_INFO,
"Usage: smartd [options]\n\n");
1621#ifdef SMARTMONTOOLS_ATTRIBUTELOG
1622 PrintOut(LOG_INFO,
" -A PREFIX|-, --attributelog=PREFIX|-\n");
1624 PrintOut(LOG_INFO,
" -A PREFIX, --attributelog=PREFIX\n");
1626 PrintOut(LOG_INFO,
" Log attribute information to {PREFIX}MODEL-SERIAL.TYPE.csv\n");
1627#ifdef SMARTMONTOOLS_ATTRIBUTELOG
1628 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_ATTRIBUTELOG
"MODEL-SERIAL.TYPE.csv]\n");
1631 PrintOut(LOG_INFO,
" -B [+]FILE, --drivedb=[+]FILE\n");
1632 PrintOut(LOG_INFO,
" Read and replace [add] drive database from FILE\n");
1634#ifdef SMARTMONTOOLS_DRIVEDBDIR
1636 PrintOut(LOG_INFO,
" and then %s", get_drivedb_path_default());
1639 PrintOut(LOG_INFO,
" -c NAME|-, --configfile=NAME|-\n");
1640 PrintOut(LOG_INFO,
" Read configuration file NAME or stdin\n");
1642#ifdef HAVE_LIBCAP_NG
1643 PrintOut(LOG_INFO,
" -C, --capabilities[=mail]\n");
1644 PrintOut(LOG_INFO,
" Drop unneeded Linux process capabilities.\n"
1645 " Warning: Mail notification may not work when used.\n\n");
1647 PrintOut(LOG_INFO,
" -d, --debug\n");
1648 PrintOut(LOG_INFO,
" Start smartd in debug mode\n\n");
1649 PrintOut(LOG_INFO,
" -D, --showdirectives\n");
1650 PrintOut(LOG_INFO,
" Print the configuration file Directives and exit\n\n");
1651 PrintOut(LOG_INFO,
" -h, --help, --usage\n");
1652 PrintOut(LOG_INFO,
" Display this help and exit\n\n");
1653 PrintOut(LOG_INFO,
" -i N, --interval=N\n");
1654 PrintOut(LOG_INFO,
" Set interval between disk checks to N seconds, where N >= 10\n\n");
1655 PrintOut(LOG_INFO,
" -l local[0-7], --logfacility=local[0-7]\n");
1657 PrintOut(LOG_INFO,
" Use syslog facility local0 - local7 or daemon [default]\n\n");
1659 PrintOut(LOG_INFO,
" Log to \"./smartd.log\", stdout, stderr [default is event log]\n\n");
1662 PrintOut(LOG_INFO,
" -n, --no-fork\n");
1663 PrintOut(LOG_INFO,
" Do not fork into background\n");
1664#ifdef HAVE_LIBSYSTEMD
1665 PrintOut(LOG_INFO,
" (systemd 'Type=notify' is assumed if $NOTIFY_SOCKET is set)\n");
1669 PrintOut(LOG_INFO,
" -p NAME, --pidfile=NAME\n");
1670 PrintOut(LOG_INFO,
" Write PID file NAME\n\n");
1671 PrintOut(LOG_INFO,
" -q WHEN, --quit=WHEN\n");
1673 PrintOut(LOG_INFO,
" -r, --report=TYPE\n");
1675#ifdef SMARTMONTOOLS_SAVESTATES
1676 PrintOut(LOG_INFO,
" -s PREFIX|-, --savestates=PREFIX|-\n");
1678 PrintOut(LOG_INFO,
" -s PREFIX, --savestates=PREFIX\n");
1680 PrintOut(LOG_INFO,
" Save disk states to {PREFIX}MODEL-SERIAL.TYPE.state\n");
1681#ifdef SMARTMONTOOLS_SAVESTATES
1682 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_SAVESTATES
"MODEL-SERIAL.TYPE.state]\n");
1685 PrintOut(LOG_INFO,
" -w NAME, --warnexec=NAME\n");
1686 PrintOut(LOG_INFO,
" Run executable NAME on warnings\n");
1688 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_SMARTDSCRIPTDIR
"/smartd_warning.sh]\n\n");
1692#ifdef HAVE_POSIX_API
1693 PrintOut(LOG_INFO,
" -u USER[:GROUP], --warn-as-user=USER[:GROUP]\n");
1694 PrintOut(LOG_INFO,
" Run warning script as non-privileged USER\n\n");
1695#elif defined(_WIN32)
1696 PrintOut(LOG_INFO,
" -u MODE, --warn-as-user=MODE\n");
1701 PrintOut(LOG_INFO,
" Running as windows service (see man page), install with:\n");
1702 PrintOut(LOG_INFO,
" smartd install [options]\n");
1703 PrintOut(LOG_INFO,
" Remove service with:\n");
1704 PrintOut(LOG_INFO,
" smartd remove\n\n");
1706 PrintOut(LOG_INFO,
" -V, --version, --license, --copyright\n");
1707 PrintOut(LOG_INFO,
" Print License, Copyright, and version information\n");
1712 if (!device->
close()){
1723 bool changed =
false;
1724 for (
unsigned i = 0; i <
s.size(); i++) {
1728 if ((
' ' <= c && c <=
'~') && !(i == 0 && c ==
'~'))
1739 return !( (
'0' <= c && c <=
'9')
1740 || (
'A' <= c && c <=
'Z')
1741 || (
'a' <= c && c <=
'z'));
1752 PrintOut(LOG_INFO,
"Device: %s, Read Summary SMART Error Log failed\n",name);
1760 PrintOut(LOG_INFO,
"Device: %s, Read Extended Comprehensive SMART Error Log failed\n",name);
1778 PrintOut(LOG_INFO,
"Device: %s, Read SMART Self Test Log Failed\n",name);
1788 for (
int i = 20; i >= 0; i--) {
1794 int status =
entry.selfteststatus >> 4;
1795 if (status == 0x0 && (
entry.selftestnumber & 0x7f) == 0x02)
1799 if (0x3 <= status && status <= 0x8) {
1804 hour =
entry.timestamp;
1814 return ((status & 0x7f) == 0x03);
1820 return ((status >> 4) == 0xf);
1827 switch (status & 0x7f) {
1828 case 0x00: msg =
"was never started";
break;
1829 case 0x02: msg =
"was completed without error";
break;
1830 case 0x03: msg =
"is in progress";
break;
1831 case 0x04: msg =
"was suspended by an interrupting command from host";
break;
1832 case 0x05: msg =
"was aborted by an interrupting command from host";
break;
1833 case 0x06: msg =
"was aborted by the device with a fatal error";
break;
1834 default: msg =
nullptr;
1838 PrintOut(((status & 0x7f) == 0x06 ? LOG_CRIT : LOG_INFO),
1839 "Device: %s, offline data collection %s%s\n", name, msg,
1840 ((status & 0x80) ?
" (auto:on)" :
""));
1842 PrintOut(LOG_INFO,
"Device: %s, unknown offline data collection status 0x%02x\n",
1850 switch (status >> 4) {
1851 case 0x0: msg =
"completed without error";
break;
1852 case 0x1: msg =
"was aborted by the host";
break;
1853 case 0x2: msg =
"was interrupted by the host with a reset";
break;
1854 case 0x3: msg =
"could not complete due to a fatal or unknown error";
break;
1855 case 0x4: msg =
"completed with error (unknown test element)";
break;
1856 case 0x5: msg =
"completed with error (electrical test element)";
break;
1857 case 0x6: msg =
"completed with error (servo/seek test element)";
break;
1858 case 0x7: msg =
"completed with error (read test element)";
break;
1859 case 0x8: msg =
"completed with error (handling damage?)";
break;
1860 default: msg =
nullptr;
1864 PrintOut(((status >> 4) >= 0x4 ? LOG_CRIT : LOG_INFO),
1865 "Device: %s, previous self-test %s\n", name, msg);
1866 else if ((status >> 4) == 0xf)
1867 PrintOut(LOG_INFO,
"Device: %s, self-test in progress, %u0%% remaining\n",
1868 name, status & 0x0f);
1870 PrintOut(LOG_INFO,
"Device: %s, unknown self-test status 0x%02x\n",
1876 unsigned char id,
const char * msg)
1881 PrintOut(LOG_INFO,
"Device: %s, can't monitor %s count - no Attribute %d\n",
1882 cfg.
name.c_str(), msg,
id);
1890 PrintOut(LOG_INFO,
"Device: %s, ignoring %s count - bogus Attribute %d value %" PRIu64
" (0x%" PRIx64
")\n",
1891 cfg.
name.c_str(), msg,
id, rawval, rawval);
1917 int set_option = 0,
bool has_value =
false)
1924 else if (set_option < 0)
1928 else if (set_option > 0)
1938 for (
const auto & prev_cfg : prev_cfgs) {
1939 if (!prev_cfg.id_is_unique)
1944 || (!prev_cfg.dev_idinfo_bc.empty() && cfg.
dev_idinfo == prev_cfg.dev_idinfo_bc)))
1947 PrintOut(LOG_INFO,
"Device: %s, same identity as %s, ignored\n",
1948 cfg.
dev_name.c_str(), prev_cfg.dev_name.c_str());
1964 const char *name = cfg.
name.c_str();
1973 PrintOut(LOG_INFO,
"Device: %s, not ATA, no IDENTIFY DEVICE Structure\n",name);
1975 PrintOut(LOG_INFO,
"Device: %s, packet devices [this device %s] not SMART capable\n",
1982 char model[40+1], serial[20+1], firmware[8+1];
1992 char wwn[64]; wwn[0] = 0;
1993 unsigned oui = 0; uint64_t unique_id = 0;
1996 snprintf(wwn,
sizeof(wwn),
"WWN:%x-%06x-%09" PRIx64
", ", naa, oui, unique_id);
2017 PrintOut(LOG_INFO,
"Device: %s, smartd database not searched (Directive: -P ignore).\n", name);
2020 std::string dbversion;
2024 PrintOut(LOG_INFO,
"Device: %s, not found in smartd database%s%s.\n", name,
2025 (!dbversion.empty() ?
" " :
""), (!dbversion.empty() ? dbversion.c_str() :
""));
2027 PrintOut(LOG_INFO,
"Device: %s, found in smartd database%s%s%s%s\n",
2028 name, (!dbversion.empty() ?
" " :
""), (!dbversion.empty() ? dbversion.c_str() :
""),
2037 bool locked = ((word128 & 0x0007) == 0x0007);
2039 PrintOut(LOG_INFO,
"Device: %s, ATA Security is **LOCKED**\n", name);
2051 PrintOut(LOG_INFO,
"Device %s: presets are:\n", name);
2063 PrintOut(LOG_INFO,
"Device: %s, lacks SMART capability\n",name);
2066 PrintOut(LOG_INFO,
"Device: %s, ATA IDENTIFY DEVICE words 82-83 don't specify if SMART capable.\n",name);
2070 PrintOut(LOG_INFO,
"Device: %s, proceeding since '-T permissive' Directive given.\n",name);
2073 PrintOut(LOG_INFO,
"Device: %s, to proceed anyway, use '-T permissive' Directive.\n",name);
2081 PrintOut(LOG_INFO,
"Device: %s, could not enable SMART capability\n",name);
2085 PrintOut(LOG_INFO,
"Device: %s, to proceed anyway, use '-T permissive' Directive.\n", name);
2089 PrintOut(LOG_INFO,
"Device: %s, proceeding since '-T permissive' Directive given.\n", name);
2092 PrintOut(LOG_INFO,
"Device: %s, proceeding since SMART is already enabled\n", name);
2099 PrintOut(LOG_INFO,
"Device: %s, could not disable SMART Attribute Autosave.\n",name);
2101 PrintOut(LOG_INFO,
"Device: %s, disabled SMART Attribute Autosave.\n",name);
2107 PrintOut(LOG_INFO,
"Device: %s, could not enable SMART Attribute Autosave.\n",name);
2109 PrintOut(LOG_INFO,
"Device: %s, enabled SMART Attribute Autosave.\n",name);
2114 PrintOut(LOG_INFO,
"Device: %s, not capable of SMART Health Status check\n",name);
2125 bool smart_val_ok =
false;
2134 PrintOut(LOG_INFO,
"Device: %s, Read SMART Values failed\n", name);
2140 smart_val_ok =
true;
2142 PrintOut(LOG_INFO,
"Device: %s, Read SMART Thresholds failed%s\n",
2143 name, (cfg.
usagefailed ?
", ignoring -f Directive" :
""));
2154 "Current_Pending_Sector"))
2159 "Offline_Uncorrectable"))
2164 PrintOut(LOG_INFO,
"Device: %s, can't monitor Temperature, ignoring -W %d,%d,%d\n",
2170 for (
int id = 1;
id <= 255;
id++) {
2178 PrintOut(LOG_INFO,
"Device: %s, no Attribute %d, ignoring -%c %d%s\n", name,
id, opt,
id, excl);
2181 if (!((prefail && cfg.
prefail) || (!prefail && cfg.
usage)))
2182 PrintOut(LOG_INFO,
"Device: %s, not monitoring %s Attributes, ignoring -%c %d%s\n", name,
2183 (prefail ?
"Prefailure" :
"Usage"), opt,
id, excl);
2194 PrintOut(LOG_INFO,
"Device: %s, could not %s SMART Automatic Offline Testing.\n",name, what);
2198 PrintOut(LOG_INFO,
"Device: %s, SMART Automatic Offline Testing unsupported...\n",name);
2201 PrintOut(LOG_INFO,
"Device: %s, %s SMART Automatic Offline Testing failed.\n", name, what);
2203 PrintOut(LOG_INFO,
"Device: %s, %sd SMART Automatic Offline Testing.\n", name, what);
2209 bool smart_logdir_ok =
false, gp_logdir_ok =
false;
2215 smart_logdir_ok =
true;
2220 gp_logdir_ok =
true;
2226 int errcnt = 0;
unsigned hour = 0;
2230 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test Log, ignoring -l selftest (override with -T permissive)\n", name);
2234 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test Log, ignoring -l selftest\n", name);
2250 PrintOut(LOG_INFO,
"Device: %s, no SMART Error Log, ignoring -l error (override with -T permissive)\n", name);
2254 PrintOut(LOG_INFO,
"Device: %s, no SMART Error Log, ignoring -l error\n", name);
2265 PrintOut(LOG_INFO,
"Device: %s, no Extended Comprehensive SMART Error Log, ignoring -l xerror (override with -T permissive)\n",
2270 PrintOut(LOG_INFO,
"Device: %s, no Extended Comprehensive SMART Error Log, ignoring -l xerror\n", name);
2274 PrintOut(LOG_INFO,
"Device: %s, SMART Error Logs report different error counts: %d != %d\n",
2288 PrintOut(LOG_INFO,
"Device: %s, no SMART Offline Data Collection capability, ignoring -l offlinests (override with -T permissive)\n", name);
2290 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test capability, ignoring -l selfteststs (override with -T permissive)\n", name);
2299 if (-1 == powermode) {
2300 PrintOut(LOG_CRIT,
"Device: %s, no ATA CHECK POWER STATUS support, ignoring -n Directive\n", name);
2303 else if (powermode!=0x00 && powermode!=0x01
2304 && powermode!=0x40 && powermode!=0x41
2305 && powermode!=0x80 && powermode!=0x81 && powermode!=0x82 && powermode!=0x83
2306 && powermode!=0xff) {
2307 PrintOut(LOG_CRIT,
"Device: %s, CHECK POWER STATUS returned %d, not ATA compliant, ignoring -n Directive\n",
2349 PrintOut(LOG_INFO,
"Device: %s, ATA settings applied: %s\n", name, msg.c_str());
2354 PrintOut(LOG_INFO,
"Device: %s, no SCT Error Recovery Control support, ignoring -l scterc\n",
2357 PrintOut(LOG_INFO,
"Device: %s, no SCT support if ATA Security is LOCKED, ignoring -l scterc\n",
2361 PrintOut(LOG_INFO,
"Device: %s, set of SCT Error Recovery Control failed\n", name);
2363 PrintOut(LOG_INFO,
"Device: %s, SCT Error Recovery Control set to: Read: %u, Write: %u\n",
2378 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n",name);
2391 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", name, cfg.
state_file.c_str());
2410 int err, req_len, avail_len, version, len;
2411 const char *device = cfg.
name.c_str();
2415 uint8_t vpdBuf[252];
2416 char lu_id[64], serial[256], vendor[40], model[40];
2419 memset(inqBuf, 0, 96);
2426 PrintOut(LOG_INFO,
"Device: %s, Both 36 and 64 byte INQUIRY failed; "
2427 "skip device [err=%d, %d]\n", device, err, err64);
2431 version = (inqBuf[2] & 0x7f);
2433 avail_len = inqBuf[4] + 5;
2434 len = (avail_len < req_len) ? avail_len : req_len;
2436 PrintOut(LOG_INFO,
"Device: %s, INQUIRY response less than 36 bytes; "
2437 "skip device\n", device);
2441 int pdt = inqBuf[0] & 0x1f;
2452 PrintOut(LOG_INFO,
"Device: %s, not a disk like device [PDT=0x%x], "
2453 "skip\n", device, pdt);
2464 if (version >= 0x3) {
2467 vpdBuf,
sizeof(vpdBuf))) {
2474 vpdBuf,
sizeof(vpdBuf))) {
2476 vpdBuf[4 + len] =
'\0';
2491 (
char *)&inqBuf[8], (
char *)&inqBuf[16], (
char *)&inqBuf[32],
2492 (lu_id[0] ?
", lu id: " :
""), (lu_id[0] ? lu_id :
""),
2493 (serial[0] ?
", S/N: " :
""), (serial[0] ? serial :
""),
2494 (si_str[0] ?
", " :
""), (si_str[0] ? si_str :
""));
2514 PrintOut(LOG_INFO,
"Device: %s, NOT READY (e.g. spun down); skip device\n", device);
2516 PrintOut(LOG_INFO,
"Device: %s, NO MEDIUM present; skip device\n", device);
2518 PrintOut(LOG_INFO,
"Device: %s, BECOMING (but not yet) READY; skip device\n", device);
2520 PrintOut(LOG_CRIT,
"Device: %s, failed Test Unit Ready [err=%d]\n", device, err);
2537 "Device: %s, Bad IEC (SMART) mode page, err=%d, skip device\n",
2546 PrintOut(LOG_INFO,
"Device: %s, IE (SMART) not enabled, skip device\n"
2547 "Try 'smartctl -s on %s' to turn on SMART features\n",
2589 uint8_t currenttemp = 0;
2590 uint8_t triptemp = 0;
2593 &asc, &ascq, ¤ttemp, &triptemp)) {
2594 PrintOut(LOG_INFO,
"Device: %s, unexpectedly failed to read SMART values\n", device);
2599 PrintOut(LOG_INFO,
"Device: %s, can't monitor Temperature, ignoring -W %d,%d,%d\n",
2610 PrintOut(LOG_INFO,
"Device: %s, does not support SMART Self-Test Log.\n", device);
2625 PrintOut(LOG_INFO,
"Device: %s, could not disable autosave (set GLTSD bit).\n",device);
2627 PrintOut(LOG_INFO,
"Device: %s, disabled autosave (set GLTSD bit).\n",device);
2633 PrintOut(LOG_INFO,
"Device: %s, could not enable autosave (clear GLTSD bit).\n",device);
2635 PrintOut(LOG_INFO,
"Device: %s, enabled autosave (cleared GLTSD bit).\n",device);
2639 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n", device);
2658 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", device, cfg.
state_file.c_str());
2675 for (
int i = 8; i < 16; i++) {
2677 return ~(uint64_t)0;
2679 uint64_t lo = val[7];
2680 for (
int i = 7-1; i >= 0; i--) {
2681 lo <<= 8; lo += val[i];
2688 uint64_t newcnt = 0)
2692 unsigned want_entries = 64;
2699 if (!read_entries) {
2700 PrintOut(LOG_INFO,
"Device: %s, Read %u entries from Error Information Log failed\n",
2701 cfg.
name.c_str(), want_entries);
2710 int err = 0, ign = 0;
2711 for (
unsigned i = 0; i < read_entries; i++) {
2731 PrintOut(LOG_INFO,
"Device: %s, NVMe error [%u], count %" PRIu64
", status 0x%04x: %s\n",
2736 std::string msg =
strprintf(
"Device: %s, NVMe error count increased from %" PRIu64
" to %" PRIu64
2737 " (%d new, %d ignored, %" PRIu64
" unknown)",
2738 cfg.
name.c_str(), oldcnt, newcnt, err, ign,
2739 (mincnt > oldcnt + 1 ? mincnt - oldcnt - 1 : 0));
2742 PrintOut(LOG_INFO,
"%s\n", msg.c_str());
2745 PrintOut(LOG_CRIT,
"%s\n", msg.c_str());
2757 const char *name = cfg.
name.c_str();
2764 PrintOut(LOG_INFO,
"Device: %s, NVMe Identify Controller failed\n", name);
2770 char model[40+1], serial[20+1], firmware[8+1];
2776 char nsstr[32] =
"", capstr[32] =
"";
2779 snprintf(nsstr,
sizeof(nsstr),
", NSID:%u",
nsid);
2786 cfg.*idinfo =
strprintf(
"%s, S/N:%s, FW:%s%s%s%s", model, serial, firmware,
2787 nsstr, (capstr[0] ?
", " :
""), capstr);
2788 if (!(nsstr[0] && id_ctrl.
nn == 1))
2811 PrintOut(LOG_INFO,
"Device: %s, failed to read NVMe SMART/Health Information\n", name);
2819 PrintOut(LOG_INFO,
"Device: %s, no Temperature sensors, ignoring -W %d,%d,%d\n",
2829 PrintOut(LOG_INFO,
"Device: %s, Error Information unavailable, ignoring -l [x]error\n", name);
2843 PrintOut(LOG_INFO,
"Device: %s, Read NVMe Self-test Log failed: %s\n", name,
2848 PrintOut(LOG_INFO,
"Device: %s, does not support NVMe Self-tests, ignoring%s%s%s%s\n", name,
2849 (cfg.
selftest ?
" -l selftest" :
""),
2865 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n", name);
2882 snprintf(nsstr,
sizeof(nsstr),
"-n%u",
nsid);
2886 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", name, cfg.
state_file.c_str());
2898 const char * name = cfg.
name.c_str();
2902 MailWarning(cfg, state, 0,
"TEST EMAIL from smartd for device: %s", name);
2917 PrintOut(LOG_INFO,
"Device: %s, is in %s mode, suspending checks\n", name,
"STANDBY (OS)");
2928 if (!device->
open()) {
2931 PrintOut(LOG_INFO,
"Device: %s, open() of %s device failed: %s\n", name, type, device->
get_errmsg());
2932 MailWarning(cfg, state, 9,
"Device: %s, unable to open %s device", name, type);
2935 PrintOut(LOG_INFO,
"Device: %s, removed %s device: %s\n", name, type, device->
get_errmsg());
2939 PrintOut(LOG_INFO,
"Device: %s, %s device still removed: %s\n", name, type, device->
get_errmsg());
2944 PrintOut(LOG_INFO,
"Device: %s, opened %s device\n", name, type);
2949 PrintOut(LOG_INFO,
"Device: %s, reconnected %s device\n", name, type);
2959 int errcnt, uint64_t hour)
2961 const char * name = cfg.
name.c_str();
2966 MailWarning(cfg, state, 8,
"Device: %s, Read SMART Self-Test Log Failed", name);
2972 PrintOut(LOG_CRIT,
"Device: %s, Self-Test Log error count increased from %d to %d\n",
2974 MailWarning(cfg, state, 3,
"Device: %s, Self-Test Log error count increased from %d to %d",
2978 else if (errcnt > 0 && state.
selfloghour != hour) {
2986 PrintOut(LOG_CRIT,
"Device: %s, new Self-Test Log error at hour timestamp %" PRIu64
"\n",
2988 MailWarning(cfg, state, 3,
"Device: %s, new Self-Test Log error at hour timestamp %" PRIu64
"\n",
2996 PrintOut(LOG_INFO,
"Device: %s, Self-Test Log error count decreased from %d to %d\n",
3031 time_t now = (!usetime ? time(
nullptr) : usetime);
3045 unsigned offsets[max_offsets] = {0, }, limits[max_offsets] = {0, };
3046 unsigned num_offsets = 1;
3048 const char * q = strchr(p,
':');
3052 unsigned offset = 0, limit = 0;
int n1 = -1, n2 = -1, n3 = -1;
3053 sscanf(p,
"%u%n-%n%u%n", &offset, &n1, &n2, &limit, &n3);
3054 if (!(n1 == 3 && (n2 < 0 || (n3 == 3+1+3 && limit > 0))))
3056 offsets[num_offsets] = offset; limits[num_offsets] = limit;
3058 p += (n3 > 0 ? n3 : n1);
3063 time_t testtime = 0;
3068 for (
unsigned i = 0; i < num_offsets; i++) {
3069 unsigned offset = offsets[i], limit = limits[i];
3071 if (0 < limit && limit < delay)
3076 int weekday = (tms->tm_wday ? tms->tm_wday : 7);
3077 for (
int j = 0; j <= maxtest; j++) {
3090 snprintf(pattern,
sizeof(pattern),
"%c/%02d/%02d/%1d/%02d",
3091 test_type_chars[j], tms->tm_mon+1, tms->tm_mday, weekday, tms->tm_hour);
3093 const unsigned len =
sizeof(
"S/01/01/1/01") - 1;
3094 snprintf(pattern + len,
sizeof(pattern) - len,
":%03u", offset);
3096 snprintf(pattern + len + 4,
sizeof(pattern) - len - 4,
"-%03u", limit);
3100 testtype = pattern[0];
3115 if ((t += 3600) > now)
3126 if (!usetime && (testtime / 3600) < (now / 3600)) {
3128 PrintOut(LOG_INFO,
"Device: %s, old test of type %c not run at %s, starting now.\n",
3129 cfg.
name.c_str(), testtype, datebuf);
3139 unsigned numdev = configs.size();
3144 PrintOut(LOG_INFO,
"\nNext scheduled self tests (at most 5 of each type per device):\n");
3147 time_t now = time(
nullptr);
3154 time_t testtime = now + seconds;
3155 for (
unsigned i = 0; i < numdev; i++) {
3165 PrintOut(LOG_INFO,
"Device: %s, will do test %d of type %c at %s\n", cfg.
name.c_str(),
3174 PrintOut(LOG_INFO,
"\nTotals [%s - %s]:\n", datenow, date);
3175 for (
unsigned i = 0; i < numdev; i++) {
3177 bool ata =
devices.at(i)->is_ata();
3182 PrintOut(LOG_INFO,
"Device: %s, will do %3d test%s of type %c\n", cfg.
name.c_str(),
3194 const char *testname =
nullptr;
3195 const char *name = cfg.
name.c_str();
3199 PrintOut(LOG_CRIT,
"Device: %s, does not support Self-Tests\n", name);
3204 if (1 == inProgress) {
3205 PrintOut(LOG_INFO,
"Device: %s, skip since Self-Test already in "
3206 "progress.\n", name);
3212 testname =
"Short Self";
3216 testname =
"Long Self";
3222 PrintOut(LOG_CRIT,
"Device: %s, not capable of %c Self-Test\n", name,
3229 PrintOut(LOG_CRIT,
"Device: %s, not capable of %s-Test\n", name,
3238 PrintOut(LOG_CRIT,
"Device: %s, execute %s-Test failed (err: %d)\n", name,
3243 PrintOut(LOG_INFO,
"Device: %s, starting scheduled %s-Test.\n", name, testname);
3252 const char *name = cfg.
name.c_str();
3258 PrintOut(LOG_CRIT,
"Device: %s, not capable of Offline or Self-Testing.\n", name);
3263 int dotest = -1, mode = 0;
3264 const char *testname =
nullptr;
3267 testname=
"Offline Immediate ";
3274 testname=
"Conveyance Self-";
3281 testname=
"Short Self-";
3288 testname=
"Long Self-";
3295 case 'c':
case 'n':
case 'r':
3296 testname =
"Selective Self-";
3312 PrintOut(LOG_CRIT,
"Device: %s, not capable of %sTest\n", name, testname);
3317 if (15==(
data.self_test_exec_status >> 4)) {
3319 PrintOut(LOG_INFO,
"Device: %s, will not skip scheduled %sTest "
3320 "despite unclear Self-Test byte (SAMSUNG Firmware bug).\n", name, testname);
3322 PrintOut(LOG_INFO,
"Device: %s, skip scheduled %sTest; %1d0%% remaining of current Self-Test.\n",
3323 name, testname, (
int)(
data.self_test_exec_status & 0x0f));
3337 PrintOut(LOG_CRIT,
"Device: %s, prepare %sTest failed\n", name, testname);
3341 PrintOut(LOG_INFO,
"Device: %s, %s test span at LBA %" PRIu64
" - %" PRIu64
" (%" PRIu64
" sectors, %u%% - %u%% of disk).\n",
3343 start, end, end - start + 1,
3353 PrintOut(LOG_CRIT,
"Device: %s, execute %sTest failed.\n", name, testname);
3359 if (testtype ==
'O')
3364 PrintOut(LOG_INFO,
"Device: %s, starting scheduled %sTest.\n", name, testname);
3370 unsigned char id,
bool increase_only,
3372 int mailtype,
const char * msg)
3388 if (!(!increase_only || prev_rawval < rawval))
3392 std::string
s =
strprintf(
"Device: %s, %" PRId64
" %s", cfg.
name.c_str(), rawval, msg);
3393 if (prev_rawval > 0 && rawval != prev_rawval)
3394 s +=
strprintf(
" (changed %+" PRId64
")", rawval - prev_rawval);
3402static const char *
fmt_temp(
unsigned char x,
char (& buf)[20])
3406 snprintf(buf,
sizeof(buf),
"%u", x);
3413 if (!(0 < currtemp && currtemp < 255)) {
3414 PrintOut(LOG_INFO,
"Device: %s, failed to read Temperature\n", cfg.
name.c_str());
3419 const char * minchg =
"", * maxchg =
"";
3420 if (currtemp > state.
tempmax) {
3433 PrintOut(LOG_INFO,
"Device: %s, initial Temperature is %d Celsius (Min/Max %s/%u%s)\n",
3436 PrintOut(LOG_INFO,
" [trip Temperature is %d Celsius]\n", (
int)triptemp);
3460 PrintOut(LOG_INFO,
"Device: %s, Temperature changed %+d Celsius to %u Celsius (Min/Max %s%s/%u%s)\n",
3468 PrintOut(LOG_CRIT,
"Device: %s, Temperature %u Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)\n",
3470 MailWarning(cfg, state, 12,
"Device: %s, Temperature %d Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)",
3474 PrintOut(LOG_INFO,
"Device: %s, Temperature %u Celsius reached limit of %u Celsius (Min/Max %s%s/%u%s)\n",
3479 if (currtemp < limit)
3480 reset_warning_mail(cfg, state, 12,
"Temperature %u Celsius dropped below %u Celsius", currtemp, limit);
3500 PrintOut(LOG_CRIT,
"Device: %s, Failed SMART usage Attribute: %d %s.\n", cfg.
name.c_str(), attr.
id, attrname.c_str());
3501 MailWarning(cfg, state, 2,
"Device: %s, Failed SMART usage Attribute: %d %s.", cfg.
name.c_str(), attr.
id, attrname.c_str());
3507 if (!( ( prefail && cfg.
prefail)
3508 || (!prefail && cfg.
usage )))
3516 if (attr.
id != prev.
id) {
3517 PrintOut(LOG_INFO,
"Device: %s, same Attribute has different ID numbers: %d = %d\n",
3518 cfg.
name.c_str(), attr.
id, prev.
id);
3523 bool valchanged =
false;
3530 bool rawchanged =
false;
3538 if (!(valchanged || rawchanged))
3542 std::string currstr, prevstr;
3564 std::string msg =
strprintf(
"Device: %s, SMART %s Attribute: %d %s changed from %s to %s",
3565 cfg.
name.c_str(), (prefail ?
"Prefailure" :
"Usage"), attr.
id,
3567 prevstr.c_str(), currstr.c_str());
3572 PrintOut(LOG_CRIT,
"%s\n", msg.c_str());
3576 PrintOut(LOG_INFO,
"%s\n", msg.c_str());
3583 bool firstpass,
bool allow_selftests)
3588 const char * name = cfg.
name.c_str();
3595 const char * mode = 0;
3596 if (0 <= powermode && powermode < 0xff) {
3601 if (powermode2 > powermode)
3602 PrintOut(LOG_INFO,
"Device: %s, CHECK POWER STATUS spins up disk (0x%02x -> 0x%02x)\n", name, powermode, powermode2);
3603 powermode = powermode2;
3655 mode=
"ACTIVE or IDLE";
3659 PrintOut(LOG_CRIT,
"Device: %s, CHECK POWER STATUS returned %d, not ATA compliant, ignoring -n Directive\n",
3672 PrintOut(LOG_INFO,
"Device: %s, is in %s mode, suspending checks\n", name, mode);
3679 PrintOut(LOG_INFO,
"Device: %s, %s mode ignored due to reached limit of skipped checks (%d check%s skipped)\n",
3686 PrintOut(LOG_INFO,
"Device: %s, is back in %s mode, resuming checks (%d check%s skipped)\n",
3697 PrintOut(LOG_INFO,
"Device: %s, not capable of SMART self-check\n",name);
3698 MailWarning(cfg, state, 5,
"Device: %s, not capable of SMART self-check", name);
3701 else if (status==1){
3702 PrintOut(LOG_CRIT,
"Device: %s, FAILED SMART self-check. BACK UP DATA NOW!\n", name);
3703 MailWarning(cfg, state, 1,
"Device: %s, FAILED SMART self-check. BACK UP DATA NOW!", name);
3717 PrintOut(LOG_CRIT,
"Device: %s, failed to read SMART Attribute Data\n", name);
3718 MailWarning(cfg, state, 6,
"Device: %s, failed to read SMART Attribute Data", name);
3728 :
"Total unreadable (pending) sectors" ));
3733 :
"Total offline uncorrectable sectors"));
3784 int errcnt1 = -1, errcnt2 = -1;
3791 int newc = (errcnt1 >= errcnt2 ? errcnt1 : errcnt2);
3796 MailWarning(cfg, state, 7,
"Device: %s, Read SMART Error Log Failed", name);
3801 PrintOut(LOG_CRIT,
"Device: %s, ATA error count increased from %d to %d\n",
3803 MailWarning(cfg, state, 4,
"Device: %s, ATA error count increased from %d to %d",
3831 const char * name = cfg.
name.c_str();
3833 uint8_t asc = 0, ascq = 0;
3834 uint8_t currenttemp = 0, triptemp = 0;
3837 &asc, &ascq, ¤ttemp, &triptemp)) {
3838 PrintOut(LOG_INFO,
"Device: %s, failed to read SMART values\n",
3840 MailWarning(cfg, state, 6,
"Device: %s, failed to read SMART values", name);
3849 PrintOut(LOG_CRIT,
"Device: %s, SMART Failure: %s\n", name, cp);
3850 MailWarning(cfg, state, 1,
"Device: %s, SMART Failure: %s", name, cp);
3851 }
else if (asc == 4 && ascq == 9) {
3852 PrintOut(LOG_INFO,
"Device: %s, self-test in progress\n", name);
3854 PrintOut(LOG_INFO,
"Device: %s, non-SMART asc,ascq: %d,%d\n",
3855 name, (
int)asc, (
int)ascq);
3857 PrintOut(LOG_INFO,
"Device: %s, SMART health: passed\n", name);
3921 || (firstpass && (
debugmode || curr_op))))
3930 uint8_t op = (curr_op ? curr_op : op0);
3931 const char * t;
char tb[32];
3933 case 0x0: t =
"";
break;
3934 case 0x1: t =
"short";
break;
3935 case 0x2: t =
"extended";
break;
3936 case 0xe: t =
"vendor specific";
break;
3937 default: snprintf(tb,
sizeof(tb),
"unknown (0x%x)", op);
3942 PrintOut(LOG_INFO,
"Device %s, %s self-test in progress, %d%% remaining\n",
3943 name, t, 100 - curr_compl);
3945 else if (!op0 || res0 == 0xf) {
3946 PrintOut(LOG_INFO,
"Device %s, no self-test has ever been run\n", name);
3950 const char * m;
char mb[48];
3952 case 0x0: m =
"completed without error";
break;
3953 case 0x1: m =
"was aborted by a self-test command";
break;
3954 case 0x2: m =
"was aborted by a controller reset";
break;
3955 case 0x3: m =
"was aborted due to a namespace removal";
break;
3956 case 0x4: m =
"was aborted by a format NVM command";
break;
3957 case 0x5: m =
"completed with error (fatal or unknown error)";
break;
3958 case 0x6: m =
"completed with error (unknown failed segment)";
break;
3959 case 0x7: m =
"completed with error (failed segments)";
break;
3960 case 0x8: m =
"was aborted (unknown reason)";
break;
3961 case 0x9: m =
"was aborted due to a sanitize operation";
break;
3962 default: snprintf(mb,
sizeof(mb),
"returned an unknown result (0x%x)", res0);
3968 snprintf(ns,
sizeof(ns),
" of NSID 0x%x", r.
nsid);
3970 PrintOut((0x5 <= res0 && res0 <= 0x7 ? LOG_CRIT : LOG_INFO),
3971 "Device %s, previous %s self-test%s %s\n", name, t, ns, m);
3983 for (
unsigned i = 0; i < 20; i++) {
3987 if (!op || res == 0xf)
3991 || !(r.
valid & 0x01)
3995 if (op == 0x2 && !res )
3998 if (!(0x5 <= res && res <= 0x7))
4015 const char *name = cfg.
name.c_str();
4018 const char *testname; uint8_t stc;
4020 case 'S': testname =
"Short"; stc = 1;
break;
4021 case 'L': testname =
"Extended"; stc = 2;
break;
4023 PrintOut(LOG_INFO,
"Device: %s, not capable of %c Self-Test\n", name, testtype);
4029 PrintOut(LOG_INFO,
"Device: %s, skip scheduled %s Self-Test (NSID 0x%x); %d%% remaining of current Self-Test.\n",
4035 PrintOut(LOG_CRIT,
"Device: %s, execute %s Self-Test failed (NSID 0x%x): %s.\n",
4045 PrintOut(LOG_INFO,
"Device: %s, starting scheduled %s Self-Test (NSID 0x%x).\n",
4046 name, testname,
nsid);
4055 const char * name = cfg.
name.c_str();
4062 PrintOut(LOG_INFO,
"Device: %s, failed to read NVMe SMART/Health Information\n", name);
4063 MailWarning(cfg, state, 6,
"Device: %s, failed to read NVMe SMART/Health Information", name);
4072 static const char *
const wnames[] =
4073 {
"LowSpare",
"Temperature",
"Reliability",
"R/O",
"VolMemBackup"};
4075 for (
unsigned b = 0, cnt = 0;
b < 8 ;
b++) {
4076 if (!(
w & (1 <<
b)))
4081 msg +=
"...";
break;
4083 if (
b >=
sizeof(wnames)/
sizeof(wnames[0])) {
4084 msg +=
"*Unknown*";
break;
4089 PrintOut(LOG_CRIT,
"Device: %s, Critical Warning (0x%02x): %s\n", name,
w, msg.c_str());
4090 MailWarning(cfg, state, 1,
"Device: %s, Critical Warning (0x%02x): %s", name,
w, msg.c_str());
4098 int c = (int)k - 273;
4114 PrintOut(LOG_CRIT,
"Device: %s, Read Self-test Log failed: %s\n",
4116 MailWarning(cfg, state, 8,
"Device: %s, Read Self-test Log failed: %s\n",
4162 bool sts1 =
false, sts2 =
false;
4163 for (
const auto & cfg : configs) {
4164 if (cfg.offlinests_ns)
4166 if (cfg.selfteststs_ns)
4173 if (!
smi()->disable_system_auto_standby(
false)) {
4175 PrintOut(LOG_CRIT,
"System auto standby enable failed: %s\n",
smi()->get_errmsg());
4177 PrintOut(LOG_INFO,
"Disable auto standby not supported, ignoring ',ns' from %s%s%s\n",
4178 (sts1 ?
"-l offlinests,ns" :
""), (sts1 && sts2 ?
" and " :
""), (sts2 ?
"-l selfteststs,ns" :
""));
4179 sts1 = sts2 =
false;
4193 bool running =
false;
4194 for (
unsigned i = 0; i < configs.size() && !running; i++) {
4210 if (!
smi()->disable_system_auto_standby(
false))
4211 PrintOut(LOG_CRIT,
"Self-test(s) completed, system auto standby enable failed: %s\n",
4212 smi()->get_errmsg());
4214 PrintOut(LOG_INFO,
"Self-test(s) completed, system auto standby enabled\n");
4218 else if (!
smi()->disable_system_auto_standby(
true)) {
4220 PrintOut(LOG_INFO,
"Self-test(s) in progress, system auto standby disable rejected: %s\n",
4221 smi()->get_errmsg());
4227 PrintOut(LOG_INFO,
"Self-test(s) in progress, system auto standby disabled\n");
4237 for (
unsigned i = 0; i < configs.size(); i++) {
4242 PrintOut(LOG_INFO,
"Device: %s, skipped (interval=%d)\n", cfg.
name.c_str(),
4283static void ToggleDebugMode()
4286 PrintOut(LOG_INFO,
"Signal USR2 - enabling debug mode\n");
4287 if (!daemon_enable_console(
"smartd [Debug]")) {
4290 PrintOut(LOG_INFO,
"smartd debug mode enabled, PID=%d\n", getpid());
4293 PrintOut(LOG_INFO,
"enable console failed\n");
4296 daemon_disable_console();
4299 PrintOut(LOG_INFO,
"Signal USR2 - debug mode disabled\n");
4308 if (timenow < wakeuptime)
4310 return timenow + ct - (timenow - wakeuptime) % ct;
4317 time_t timenow = time(
nullptr);
4318 unsigned n = configs.size();
4328 for (
unsigned i = 0; i < n; i++) {
4334 if (!wakeuptime || state.
wakeuptime < wakeuptime)
4343 bool no_skip =
false;
4347 if (wakeuptime > timenow + ct) {
4348 PrintOut(LOG_INFO,
"System clock time adjusted to the past. Resetting next wakeup time.\n");
4349 wakeuptime = timenow + ct;
4350 for (
auto & state : states)
4351 state.wakeuptime = 0;
4356 sleep(wakeuptime+addtime-timenow);
4360 if (caughtsigUSR2) {
4366 timenow = time(
nullptr);
4369 if (!addtime && timenow > wakeuptime+60) {
4371 PrintOut(LOG_INFO,
"Sleep time was %d seconds too long, assuming wakeup from standby mode.\n",
4372 (
int)(timenow-wakeuptime));
4374 addtime = timenow-wakeuptime+20;
4376 int nextcheck = ct - addtime % ct;
4377 if (nextcheck <= 20)
4378 addtime += nextcheck;
4384 PrintOut(LOG_INFO,
"Signal USR1 - checking devices now rather than in %d seconds.\n",
4385 wakeuptime-timenow>0?(
int)(wakeuptime-timenow):0);
4387 sigwakeup = no_skip =
true;
4392 for (
auto & state : states)
4393 state.skip = (!no_skip && timenow < state.wakeuptime);
4405 PrintOut(priority,
"never[,N][,q], sleep[,N][,q], standby[,N][,q], idle[,N][,q]");
4408 PrintOut(priority,
"valid_regular_expression");
4411 PrintOut(priority,
"%s",
smi()->get_valid_dev_types_str().c_str());
4414 PrintOut(priority,
"normal, permissive");
4421 PrintOut(priority,
"error, selftest");
4424 PrintOut(priority,
"\"once\", \"always\", \"daily\", \"diminishing\", \"test\", \"exec\"");
4430 PrintOut(priority,
"use, ignore, show, showall");
4436 PrintOut(priority,
"aam,[N|off], apm,[N|off], lookahead,[on|off], dsn,[on|off] "
4437 "security-freeze, standby,[N|off], wcache,[on|off]");
4440 PrintOut(priority,
"i=N, interval=N");
4446static int GetInteger(
const char *arg,
const char *name,
const char *token,
int lineno,
const char *cfgfile,
4447 int min,
int max,
char * suffix = 0)
4451 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s takes integer argument from %d to %d.\n",
4452 cfgfile, lineno, name, token, min, max);
4458 int val = strtol(arg,&endptr,10);
4462 if (!strcmp(endptr, suffix))
4463 endptr += strlen(suffix);
4468 if (!(!*endptr && min <= val && val <= max)) {
4469 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s has argument: %s; needs integer from %d to %d.\n",
4470 cfgfile, lineno, name, token, arg, min, max);
4480static int Get3Integers(
const char *arg,
const char *name,
const char *token,
int lineno,
const char *cfgfile,
4481 unsigned char *val1,
unsigned char *val2,
unsigned char *val3)
4483 unsigned v1 = 0, v2 = 0, v3 = 0;
4484 int n1 = -1, n2 = -1, n3 = -1, len;
4486 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s takes 1-3 integer argument(s) from 0 to 255.\n",
4487 cfgfile, lineno, name, token);
4492 if (!( sscanf(arg,
"%u%n,%u%n,%u%n", &v1, &n1, &v2, &n2, &v3, &n3) >= 1
4493 && (n1 == len || n2 == len || n3 == len) && v1 <= 255 && v2 <= 255 && v3 <= 255)) {
4494 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s has argument: %s; needs 1-3 integer(s) from 0 to 255.\n",
4495 cfgfile, lineno, name, token, arg);
4498 *val1 = (
unsigned char)v1; *val2 = (
unsigned char)v2; *val3 = (
unsigned char)v3;
4506static const char * strtok_dequote(
const char * delimiters)
4508 const char * t = strtok(
nullptr, delimiters);
4509 if (!t || t[0] !=
'"')
4512 static std::string token;
4515 t = strtok(
nullptr, delimiters);
4519 int len = strlen(t);
4520 if (t[len-1] ==
'"') {
4521 token += std::string(t, len-1);
4526 return token.c_str();
4538 const char * name = cfg.
name.c_str();
4540 const char *delim =
" \n\t";
4543 const char *arg = 0;
4550 if (*token!=
'-' || strlen(token)!=2) {
4551 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): unknown Directive: %s\n",
4553 PrintOut(LOG_CRIT,
"Run smartd -D to print a list of valid Directives.\n");
4562 char plus[] =
"+", excl[] =
"!";
4567 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 0, 255, plus)) < 0)
4575 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 0, 255, plus)) < 0)
4583 if (!(arg = strtok(
nullptr, delim))) {
4585 }
else if (!strcmp(arg,
"normal")) {
4590 }
else if (!strcmp(arg,
"permissive")) {
4599 if (!(arg = strtok(
nullptr, delim))) {
4601 }
else if (!strcmp(arg,
"ignore")) {
4603 }
else if (!strcmp(arg,
"removable")) {
4605 }
else if (!strcmp(arg,
"auto")) {
4610 scan_types.push_back(arg);
4615 if (!(arg = strtok(
nullptr, delim)))
4643 if (!(arg = strtok(
nullptr, delim))) {
4645 }
else if (!strcmp(arg,
"selftest")) {
4648 }
else if (!strcmp(arg,
"error")) {
4651 }
else if (!strcmp(arg,
"xerror")) {
4654 }
else if (!strcmp(arg,
"offlinests")) {
4657 }
else if (!strcmp(arg,
"offlinests,ns")) {
4660 }
else if (!strcmp(arg,
"selfteststs")) {
4663 }
else if (!strcmp(arg,
"selfteststs,ns")) {
4666 }
else if (!strncmp(arg,
"scterc,",
sizeof(
"scterc,")-1)) {
4668 unsigned rt = ~0, wt = ~0;
int nc = -1;
4669 sscanf(arg,
"scterc,%u,%u%n", &rt, &wt, &nc);
4670 if (nc == (
int)strlen(arg) && rt <= 999 && wt <= 999) {
4693 if (!(arg = strtok(
nullptr, delim))) {
4695 }
else if (!strcmp(arg,
"on")) {
4697 }
else if (!strcmp(arg,
"off")) {
4705 if (!(arg = strtok(
nullptr, delim)))
4708 char *endptr =
nullptr;
4709 char *next = strchr(
const_cast<char*
>(arg),
',');
4716 if (!strcmp(arg,
"never"))
4718 else if (!strcmp(arg,
"sleep"))
4720 else if (!strcmp(arg,
"standby"))
4722 else if (!strcmp(arg,
"idle"))
4728 if (!badarg && next) {
4734 next = endptr + (*endptr !=
'\0');
4738 if (*next !=
'\0') {
4739 if (!strcmp(
"q", next))
4750 if (!(arg = strtok(
nullptr, delim))) {
4752 }
else if (!strcmp(arg,
"on")) {
4754 }
else if (!strcmp(arg,
"off")) {
4763 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous Test Directive -s %s\n",
4768 if (!(arg = strtok(
nullptr, delim))) {
4775 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): -s argument \"%s\" is INVALID extended regular expression. %s.\n",
4784 "[^]$()*+./:?^[|0-9LSCOncr-]+|"
4785 ":[0-9]{0,2}($|[^0-9])|:[0-9]{4,}|"
4786 ":[0-9]{3}-(000|[0-9]{0,2}($|[^0-9])|[0-9]{4,})"
4789 if (syntax_check.
execute(arg, 1, &range) && 0 <= range.rm_so && range.rm_so < range.rm_eo)
4790 PrintOut(LOG_INFO,
"File %s line %d (drive %s): warning, \"%.*s\" looks odd in "
4791 "extended regular expression \"%s\"\n",
4792 configfile, lineno, name, (
int)(range.rm_eo - range.rm_so), arg + range.rm_so, arg);
4797 if (!(arg = strtok(
nullptr, delim)))
4801 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous Address Directive -m %s\n",
4808 if (!(arg = strtok(
nullptr, delim)))
4810 else if (!strcmp(arg,
"once"))
4812 else if (!strcmp(arg,
"always"))
4814 else if (!strcmp(arg,
"daily"))
4816 else if (!strcmp(arg,
"diminishing"))
4818 else if (!strcmp(arg,
"test"))
4820 else if (!strcmp(arg,
"exec")) {
4824 arg = strtok_dequote(delim);
4825 if (arg && arg[0] ==
'"') {
4826 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive %s 'exec' argument: missing closing quote\n",
4831 arg = strtok(
nullptr, delim);
4834 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive %s 'exec' argument must be followed by executable path.\n",
4840 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous mail Directive -M exec %s\n",
4849 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255)) < 0)
4855 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255)) < 0)
4861 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255, excl)) < 0)
4869 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255, excl)) < 0)
4883 if (!(arg = strtok(
nullptr, delim))) {
4891 if (!(arg = strtok(
nullptr, delim))) {
4893 }
else if (!strcmp(arg,
"use")) {
4895 }
else if (!strcmp(arg,
"ignore")) {
4897 }
else if (!strcmp(arg,
"show")) {
4899 }
else if (!strcmp(arg,
"showall")) {
4908 if (!(arg = strtok(
nullptr, delim))) {
4912 char arg2[16+1];
unsigned uval;
4913 int n1 = -1, n2 = -1, n3 = -1, len = strlen(arg);
4914 if (sscanf(arg,
"%16[^,=]%n%*[,=]%n%u%n", arg2, &n1, &n2, &uval, &n3) >= 1
4915 && (n1 == len || n2 > 0)) {
4916 bool on = (n2 > 0 && !strcmp(arg+n2,
"on"));
4917 bool off = (n2 > 0 && !strcmp(arg+n2,
"off"));
4921 if (!strcmp(arg2,
"aam")) {
4924 else if (uval <= 254)
4929 else if (!strcmp(arg2,
"apm")) {
4932 else if (1 <= uval && uval <= 254)
4937 else if (!strcmp(arg2,
"lookahead")) {
4945 else if (!strcmp(arg,
"security-freeze")) {
4948 else if (!strcmp(arg2,
"standby")) {
4951 else if (uval <= 255)
4956 else if (!strcmp(arg2,
"wcache")) {
4964 else if (!strcmp(arg2,
"dsn")) {
4983 if (!(arg = strtok(
nullptr, delim))) {
4987 int n = 0, nc = -1, len = strlen(arg);
4988 if ( ( sscanf(arg,
"i=%d%n", &n, &nc) == 1
4989 || sscanf(arg,
"interval=%d%n", &n, &nc) == 1)
4990 && nc == len && n >= 10)
4999 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): unknown Directive: %s\n",
5001 PrintOut(LOG_CRIT,
"Run smartd -D to print a list of valid Directives.\n");
5005 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Missing argument to %s Directive\n",
5009 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Invalid argument to %s Directive: %s\n",
5012 if (missingarg || badarg) {
5013 PrintOut(LOG_CRIT,
"Valid arguments to %s Directive are: ", token);
5023#define SCANDIRECTIVE "DEVICESCAN"
5037 const char *delim =
" \n\t";
5040 const char * name = strtok(line, delim);
5041 if (!name || *name ==
'#')
5046 if (!strcmp(
"DEFAULT", name)) {
5054 conf_entries.push_back(default_conf);
5056 dev_config & cfg = (retval ? conf_entries.back() : default_conf);
5063 while (
char * token = strtok(
nullptr, delim)) {
5077 if (retval != -1 && scan_types.size() > 1) {
5078 PrintOut(LOG_CRIT,
"Drive: %s, invalid multiple -d TYPE Directives on line %d of file %s\n",
5094 PrintOut(LOG_INFO,
"Drive: %s, implied '-a' Directive on line %d of file %s\n",
5109 PrintOut(LOG_CRIT,
"Drive: %s, -M Directive(s) on line %d of file %s need -m ADDRESS Directive\n",
5118 PrintOut(LOG_CRIT,
"Drive: %s, -m <nomailer> Directive on line %d of file %s needs -M exec Directive\n",
5143 const int MAXLINELEN = 256;
5145 const int MAXCONTLINE = 1023;
5152 int ret = (errno!=ENOENT ? -3 : -2);
5153 PrintOut(LOG_CRIT,
"%s: Unable to open configuration file %s\n",
5169 if (
ParseConfigLine(conf_entries, default_conf, scan_types, 0, fakeconfig) != -1)
5170 throw std::logic_error(
"Internal error parsing " SCANDIRECTIVE);
5175 setmode(fileno(f), O_TEXT);
5182 int lineno = 1, cont = 0, contlineno = 0;
5183 char line[MAXLINELEN+2];
5184 char fullline[MAXCONTLINE+1];
5187 int len=0,scandevice;
5193 memset(line,0,
sizeof(line));
5196 code=fgets(line, MAXLINELEN+2, f);
5201 scandevice =
ParseConfigLine(conf_entries, default_conf, scan_types, contlineno, fullline);
5219 if (len>MAXLINELEN){
5221 if (line[len-1]==
'\n')
5222 warn=
"(including newline!) ";
5225 PrintOut(LOG_CRIT,
"Error: line %d of file %s %sis more than MAXLINELEN=%d characters.\n",
5226 (
int)contlineno,
configfile,warn,(
int)MAXLINELEN);
5231 if ((comment=strchr(line,
'#'))){
5237 if (cont+len>MAXCONTLINE){
5238 PrintOut(LOG_CRIT,
"Error: continued line %d (actual line %d) of file %s is more than MAXCONTLINE=%d characters.\n",
5239 lineno, (
int)contlineno,
configfile, (
int)MAXCONTLINE);
5244 snprintf(fullline+cont,
sizeof(fullline)-cont,
"%s" ,line);
5248 if ( (lastslash=strrchr(line,
'\\')) && !strtok(lastslash+1,
" \n\t")){
5249 *(fullline+(cont-len)+(lastslash-line))=
' ';
5255 scandevice =
ParseConfigLine(conf_entries, default_conf, scan_types, contlineno, fullline);
5279 PrintOut(LOG_CRIT,
"=======> VALID ARGUMENTS ARE: ");
5281 PrintOut(LOG_CRIT,
"Error constructing argument list for option %c", opt);
5291 if (path.empty() || path[0] ==
'/')
5296 PrintOut(LOG_CRIT,
"=======> INVALID ARGUMENT TO -%c: %s <=======\n\n", option, path.c_str());
5297 PrintOut(LOG_CRIT,
"Error: relative path names are not allowed\n\n");
5308 configfile = SMARTMONTOOLS_SYSCONFDIR
"/smartd.conf";
5309 warning_script = SMARTMONTOOLS_SMARTDSCRIPTDIR
"/smartd_warning.sh";
5312 static std::string configfile_str = exedir +
"/smartd.conf";
5318 static const char shortopts[] =
"c:l:q:dDni:p:r:s:A:B:w:Vh?"
5319#if defined(HAVE_POSIX_API) || defined(_WIN32)
5322#ifdef HAVE_LIBCAP_NG
5327 struct option longopts[] = {
5328 {
"configfile", required_argument, 0,
'c' },
5329 {
"logfacility", required_argument, 0,
'l' },
5330 {
"quit", required_argument, 0,
'q' },
5331 {
"debug", no_argument, 0,
'd' },
5332 {
"showdirectives", no_argument, 0,
'D' },
5333 {
"interval", required_argument, 0,
'i' },
5335 {
"no-fork", no_argument, 0,
'n' },
5337 {
"service", no_argument, 0,
'n' },
5339 {
"pidfile", required_argument, 0,
'p' },
5340 {
"report", required_argument, 0,
'r' },
5341 {
"savestates", required_argument, 0,
's' },
5342 {
"attributelog", required_argument, 0,
'A' },
5343 {
"drivedb", required_argument, 0,
'B' },
5344 {
"warnexec", required_argument, 0,
'w' },
5345 {
"version", no_argument, 0,
'V' },
5346 {
"license", no_argument, 0,
'V' },
5347 {
"copyright", no_argument, 0,
'V' },
5348 {
"help", no_argument, 0,
'h' },
5349 {
"usage", no_argument, 0,
'h' },
5350#if defined(HAVE_POSIX_API) || defined(_WIN32)
5351 {
"warn-as-user", required_argument, 0,
'u' },
5353#ifdef HAVE_LIBCAP_NG
5354 {
"capabilities", optional_argument, 0,
'C' },
5360 bool badarg =
false;
5361 const char * badarg_msg =
nullptr;
5362 bool use_default_db =
true;
5366 while ((optchar = getopt_long(argc, argv, shortopts, longopts,
nullptr)) != -1) {
5375 if (!strcmp(optarg,
"nodev"))
5377 else if (!strcmp(optarg,
"nodev0")) {
5381 else if (!strcmp(optarg,
"nodevstartup"))
5383 else if (!strcmp(optarg,
"nodev0startup")) {
5387 else if (!strcmp(optarg,
"errors"))
5389 else if (!strcmp(optarg,
"errors,nodev0")) {
5393 else if (!strcmp(optarg,
"never"))
5395 else if (!strcmp(optarg,
"onecheck")) {
5399 else if (!strcmp(optarg,
"showtests")) {
5408 if (!strcmp(optarg,
"daemon"))
5410 else if (!strcmp(optarg,
"local0"))
5412 else if (!strcmp(optarg,
"local1"))
5414 else if (!strcmp(optarg,
"local2"))
5416 else if (!strcmp(optarg,
"local3"))
5418 else if (!strcmp(optarg,
"local4"))
5420 else if (!strcmp(optarg,
"local5"))
5422 else if (!strcmp(optarg,
"local6"))
5424 else if (!strcmp(optarg,
"local7"))
5448 lchecktime = strtol(optarg, &tailptr, 10);
5449 if (*tailptr !=
'\0' || lchecktime < 10 || lchecktime > INT_MAX || errno) {
5452 PrintOut(LOG_CRIT,
"======> INVALID INTERVAL: %s <=======\n", optarg);
5453 PrintOut(LOG_CRIT,
"======> INTERVAL MUST BE INTEGER BETWEEN %d AND %d <=======\n", 10, INT_MAX);
5454 PrintOut(LOG_CRIT,
"\nUse smartd -h to get a usage summary\n\n");
5462 int n1 = -1, n2 = -1, len = strlen(optarg);
5463 char s[9+1];
unsigned i = 1;
5464 sscanf(optarg,
"%9[a-z]%n,%u%n",
s, &n1, &i, &n2);
5465 if (!((n1 == len || n2 == len) && 1 <= i && i <= 4)) {
5467 }
else if (!strcmp(
s,
"ioctl")) {
5469 }
else if (!strcmp(
s,
"ataioctl")) {
5471 }
else if (!strcmp(
s,
"scsiioctl")) {
5473 }
else if (!strcmp(
s,
"nvmeioctl")) {
5482 if (strcmp(optarg,
"-"))
5501 const char * path = optarg;
5502 if (*path ==
'+' && path[1])
5505 use_default_db =
false;
5515#ifdef HAVE_POSIX_API
5517 warn_as_user =
false;
5518 if (strcmp(optarg,
"-")) {
5519 warn_uname = warn_gname =
"unknown";
5520 badarg_msg =
parse_ugid(optarg, warn_uid, warn_gid,
5521 warn_uname, warn_gname );
5524 warn_as_user =
true;
5527#elif defined(_WIN32)
5529 if (!strcmp(optarg,
"restricted"))
5530 warn_as_restr_user =
true;
5531 else if (!strcmp(optarg,
"unchanged"))
5532 warn_as_restr_user =
false;
5542#ifdef HAVE_LIBCAP_NG
5546 capabilities_mode = 1;
5547 else if (!strcmp(optarg,
"mail"))
5548 capabilities_mode = 2;
5566 arg = argv[optind <= argc ? optind - 1 : argc - 1];
5568 if (arg[1] ==
'-' && optchar !=
'h') {
5570 if (optopt && strchr(shortopts, optopt)) {
5571 PrintOut(LOG_CRIT,
"=======> ARGUMENT REQUIRED FOR OPTION: %s <=======\n",arg+2);
5574 PrintOut(LOG_CRIT,
"=======> UNRECOGNIZED OPTION: %s <=======\n\n",arg+2);
5576 PrintOut(LOG_CRIT,
"\nUse smartd --help to get a usage summary\n\n");
5581 if (strchr(shortopts, optopt)){
5582 PrintOut(LOG_CRIT,
"=======> ARGUMENT REQUIRED FOR OPTION: %c <=======\n",optopt);
5585 PrintOut(LOG_CRIT,
"=======> UNRECOGNIZED OPTION: %c <=======\n\n",optopt);
5587 PrintOut(LOG_CRIT,
"\nUse smartd -h to get a usage summary\n\n");
5595 if (badarg || badarg_msg) {
5601 PrintOut(LOG_CRIT,
"=======> INVALID ARGUMENT TO -%c: %s <======= \n", optchar, optarg);
5603 PrintOut(LOG_CRIT,
"%s\n", badarg_msg);
5606 PrintOut(LOG_CRIT,
"\nUse smartd -h to get a usage summary\n\n");
5612 if (argc > optind) {
5615 PrintOut(LOG_CRIT,
"=======> UNRECOGNIZED ARGUMENT: %s <=======\n\n", argv[optind]);
5616 PrintOut(LOG_CRIT,
"\nUse smartd -h to get a usage summary\n\n");
5624 PrintOut(LOG_CRIT,
"=======> INVALID CHOICE OF OPTIONS: -d and -p <======= \n\n");
5625 PrintOut(LOG_CRIT,
"Error: pid file %s not written in debug (-d) mode\n\n",
pid_file.c_str());
5640 if (warn_as_restr_user && !popen_as_restr_check()) {
5643 PrintOut(LOG_CRIT,
"Option '--warn-as-user=restricted' is not effective if the current user\n");
5644 PrintOut(LOG_CRIT,
"is the local 'SYSTEM' or 'Administrator' account\n\n");
5678 if (!
smi()->scan_smart_devices(devlist, types)) {
5679 PrintOut(LOG_CRIT,
"DEVICESCAN failed: %s\n",
smi()->get_errmsg());
5684 if (devlist.
size() == 0)
5688 while (scanned_devs.
size() < conf_entries.size())
5692 for (
unsigned i = 0; i < devlist.
size(); i++) {
5698 conf_entries.push_back(base_cfg);
5711 return devlist.
size();
5724 conf_entries.clear();
5735 else if (!conf_entries.empty()) {
5740 conf_entries.pop_back();
5751 if (conf_entries.empty())
5752 PrintOut(LOG_CRIT,
"In the system's table of devices NO devices found to scan\n");
5757 return conf_entries.size();
5770 PrintOut(LOG_INFO,
"Device: %s, unable to autodetect device type\n", cfg.
name.c_str());
5772 PrintOut(LOG_INFO,
"Device: %s, unsupported device type '%s'\n", cfg.
name.c_str(), cfg.
dev_type.c_str());
5786 dev.
replace( dev->autodetect_open() );
5789 if (oldinfo.
dev_type != dev->get_dev_type())
5790 PrintOut(LOG_INFO,
"Device: %s, type changed from '%s' to '%s'\n",
5791 cfg.
name.c_str(), oldinfo.
dev_type.c_str(), dev->get_dev_type());
5794 if (!dev->is_open()) {
5796 PrintOut(LOG_INFO,
"Device: %s, open() failed: %s\n", dev->get_info_name(), dev->get_errmsg());
5801 cfg.
name = dev->get_info().info_name;
5802 PrintOut(LOG_INFO,
"Device: %s, opened\n", cfg.
name.c_str());
5805 const char * typemsg;
5809 status =
ATADeviceScan(cfg, state, dev->to_ata(), prev_cfgs);
5812 else if (dev->is_scsi()){
5817 else if (dev->is_nvme()) {
5822 PrintOut(LOG_INFO,
"Device: %s, neither ATA, SCSI nor NVMe device\n", cfg.
name.c_str());
5829 PrintOut(scanning ? LOG_INFO : LOG_CRIT,
5830 "Unable to register %s device %s at line %d of file %s\n",
5833 PrintOut(LOG_INFO,
"Unable to register %s device %s\n",
5834 typemsg, cfg.
name.c_str());
5855 typedef std::map<std::string, std::string> prev_unique_names_map;
5856 prev_unique_names_map prev_unique_names;
5859 for (
unsigned i = 0; i < conf_entries.size(); i++) {
5865 pout(
"Device: %s%s%s%s, unique name: %s\n", cfg.
name.c_str(),
5867 (!cfg.
dev_type.empty() ?
"]" :
""), unique_name.c_str());
5872 PrintOut(LOG_INFO,
"Device: %s%s%s%s, ignored\n", cfg.
name.c_str(),
5874 (!cfg.
dev_type.empty() ?
"]" :
""));
5875 prev_unique_names[unique_name] = cfg.
name;
5882 bool scanning =
false;
5883 if (i < scanned_devs.
size()) {
5884 dev = scanned_devs.
release(i);
5887 prev_unique_names_map::iterator ui = prev_unique_names.find(unique_name);
5888 if (ui != prev_unique_names.end()) {
5889 bool ne = (ui->second != cfg.
name);
5890 PrintOut(LOG_INFO,
"Device: %s, %s%s, ignored\n", dev->get_info_name(),
5891 (ne ?
"same as " :
"duplicate"), (ne ? ui->second.c_str() :
""));
5909 PrintOut(LOG_CRIT,
"Unable to register device %s (no Directive -d removable). Exiting.\n",
5913 PrintOut(LOG_INFO,
"Device: %s, not available\n", cfg.
name.c_str());
5915 prev_unique_names[unique_name] = cfg.
name;
5921 configs.push_back(cfg);
5922 states.push_back(state);
5926 prev_unique_names[unique_name] = cfg.
name;
5931 unsigned factor = 0;
5932 for (
auto & cfg : configs) {
5935 if (!cfg.test_regex.empty())
5936 cfg.test_offset_factor = factor++;
5975 bool firstpass =
true, write_states_always =
true;
5976 time_t wakeuptime = 0;
5988 "Signal HUP - rereading configuration file %s\n":
5989 "\a\nSignal INT - rereading configuration file %s (" SIGQUIT_KEYNAME " quits)\n\n",
6006 if (!(configs.size() ==
devices.size() && configs.size() == states.size()))
6007 throw std::logic_error(
"Invalid result from RegisterDevices");
6013 PrintOut(LOG_INFO,
"Reusing previous configuration\n");
6025 PrintOut((status ? LOG_CRIT : LOG_INFO),
6026 "Unable to monitor any SMART enabled devices. Exiting.\n");
6031 int numata = 0, numscsi = 0;
6032 for (
unsigned i = 0; i <
devices.size(); i++) {
6039 PrintOut(LOG_INFO,
"Monitoring %d ATA/SATA, %d SCSI/SAS and %d NVMe devices\n",
6040 numata, numscsi, (
int)
devices.size() - numata - numscsi);
6053 write_states_always =
true;
6064 write_states_always =
false;
6072 PrintOut(LOG_INFO,
"Started with '-q onecheck' option. All devices successfully checked once.\n"
6073 "smartd is exiting (exit status 0)\n");
6095 wakeuptime = time(
nullptr);
6101 wakeuptime =
dosleep(wakeuptime, configs, states, write_states_always);
6108 PrintOut(LOG_INFO,
"smartd received signal %d: %s\n",
6113 PrintOut(LOG_CRIT,
"smartd received unexpected signal %d: %s\n",
6132 PrintOut(LOG_CRIT,
"Can't unlink PID file %s (%s).\n",
6133 pid_file.c_str(), strerror(errno));
6136 PrintOut((status ? LOG_CRIT : LOG_INFO),
"smartd is exiting (exit status %d)\n", status);
6146static int smartd_main(
int argc,
char **argv)
6154 catch (
const std::bad_alloc & ) {
6156 PrintOut(LOG_CRIT,
"Smartd: Out of memory\n");
6159 catch (
const std::exception & ex) {
6161 PrintOut(LOG_CRIT,
"Smartd: Exception: %s\n", ex.what());
6167 PrintOut(LOG_CRIT,
"Smartd: Internal Error: %d device object(s) left at exit.\n",
6173 PrintOut(LOG_CRIT,
"Please inform " PACKAGE_BUGREPORT
", including output of smartd -V.\n");
6177 daemon_winsvc_exitcode = status;
6185int main(
int argc,
char **argv){
6187 static const daemon_winsvc_options svc_opts = {
6189 "smartd",
"SmartD Service",
6191 "Controls and monitors storage devices using the Self-Monitoring, "
6192 "Analysis and Reporting Technology System (SMART) built into "
6193 "ATA/SATA and SCSI/SAS hard drives and solid-state drives. "
6194 "www.smartmontools.org"
6199 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 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 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 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)
vsnprintf(buf, sizeof(buf), fmt, ap)
static int standby_disable_state
static void notify_msg(const char *)
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 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 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 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)
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 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 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
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)