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);
106#elif defined(HAVE_SIGACTION)
109 sa.sa_handler = SIG_DFL;
110 sigaction(sig, (
struct sigaction *)0, &sa);
111 if (sa.sa_handler == SIG_IGN)
114 memset(&sa, 0,
sizeof(sa));
115 sa.sa_handler = handler;
116 sa.sa_flags = SA_RESTART;
117 sigaction(sig, &sa, (
struct sigaction *)0);
119#elif defined(HAVE_SIGSET)
121 if (sigset(sig, handler) == SIG_IGN)
122 sigset(sig, SIG_IGN);
128 if (signal(sig, handler) == SIG_IGN)
129 signal(sig, SIG_IGN);
139#define EXIT_BADCONF 2
140#define EXIT_STARTUP 3
143#define EXIT_READCONF 6
146#define EXIT_BADCODE 10
148#define EXIT_BADDEV 16
151#define EXIT_SIGNAL 254
167#ifdef SMARTMONTOOLS_SAVESTATES
168 = SMARTMONTOOLS_SAVESTATES
174#ifdef SMARTMONTOOLS_ATTRIBUTELOG
175 = SMARTMONTOOLS_ATTRIBUTELOG
191static bool warn_as_user;
192static uid_t warn_uid;
193static gid_t warn_gid;
194static std::string warn_uname, warn_gname;
197static bool warn_as_restr_user;
224static volatile int caughtsigUSR2=0;
235static void PrintOut(
int priority,
const char *
fmt, ...)
238#ifdef HAVE_LIBSYSTEMD
241static bool notify_enabled =
false;
242static bool notify_ready =
false;
246 if (!getenv(
"NOTIFY_SOCKET"))
248 notify_enabled =
true;
256 PrintOut(LOG_CRIT,
"Option -n (--no-fork) is required if 'Type=notify' is set.\n");
268 const char * notify =
"EXTEND_TIMEOUT_USEC=20000000";
270 pout(
"sd_notify(0, \"%s\")\n", notify);
273 sd_notify(0, notify);
276static void notify_msg(
const char * msg,
bool ready =
false)
281 pout(
"sd_notify(0, \"%sSTATUS=%s\")\n", (ready ?
"READY=1\\n" :
""), msg);
284 sd_notifyf(0,
"%sSTATUS=%s", (ready ?
"READY=1\n" :
""), msg);
292 snprintf(msg,
sizeof(msg),
"Checking %d device%s ...",
293 numdev, (numdev != 1 ?
"s" :
""));
297static void notify_wait(time_t wakeuptime,
int numdev)
301 char ts[16] =
"";
struct tm tmbuf;
304 snprintf(msg,
sizeof(msg),
"Next check of %d device%s will start at %s",
305 numdev, (numdev != 1 ?
"s" :
""), ts);
316 case 0: msg =
"Exiting ...";
break;
317 case EXIT_BADCMD: msg =
"Error in command line (see SYSLOG)";
break;
319 case EXIT_READCONF: msg =
"Error in config file (see SYSLOG)";
break;
320 case EXIT_BADDEV: msg =
"Unable to register a device (see SYSLOG)";
break;
321 case EXIT_NODEV: msg =
"No devices to monitor";
break;
322 default: msg =
"Error (see SYSLOG)";
break;
335 if (getenv(
"NOTIFY_SOCKET")) {
336 PrintOut(LOG_CRIT,
"This version of smartd was build without 'Type=notify' support.\n");
372 bool is_set(
int id,
unsigned char flag)
const
373 {
return (0 <
id &&
id < (
int)
sizeof(
m_flags) && (
m_flags[
id] & flag)); }
377 if (0 <
id &&
id < (
int)
sizeof(
m_flags))
601 | ((uint64_t)ta.
raw[3] << 24)
602 | ((uint64_t)ta.
raw[4] << 32)
603 | ((uint64_t)ta.
raw[5] << 40);
617 memset(ta.
raw, 0,
sizeof(ta.
raw));
622 ta.
raw[0] = (
unsigned char) pa.
raw;
623 ta.
raw[1] = (
unsigned char)(pa.
raw >> 8);
624 ta.
raw[2] = (
unsigned char)(pa.
raw >> 16);
625 ta.
raw[3] = (
unsigned char)(pa.
raw >> 24);
626 ta.
raw[4] = (
unsigned char)(pa.
raw >> 32);
627 ta.
raw[5] = (
unsigned char)(pa.
raw >> 40);
639 "|(self-test-errors)"
640 "|(self-test-last-err-hour)"
641 "|(scheduled-test-next-check)"
642 "|(selective-test-last-start)"
643 "|(selective-test-last-end)"
645 "|(mail\\.([0-9]+)\\."
651 "|(ata-smart-attribute\\.([0-9]+)\\."
659 "|(nvme-err-log-entries)"
661 " *= *([0-9]+)[ \n]*$"
664 const int nmatch = 1+25;
668 if (
match[nmatch-1].rm_so < 0)
671 uint64_t val = strtoull(line +
match[nmatch-1].rm_so, (
char **)0, 10);
674 if (
match[++m].rm_so >= 0)
675 state.
tempmin = (
unsigned char)val;
676 else if (
match[++m].rm_so >= 0)
677 state.
tempmax = (
unsigned char)val;
678 else if (
match[++m].rm_so >= 0)
680 else if (
match[++m].rm_so >= 0)
682 else if (
match[++m].rm_so >= 0)
684 else if (
match[++m].rm_so >= 0)
686 else if (
match[++m].rm_so >= 0)
688 else if (
match[++m].rm_so >= 0)
690 else if (
match[m+=2].rm_so >= 0) {
691 int i = atoi(line+
match[m].rm_so);
696 if (
match[m+=2].rm_so >= 0)
698 else if (
match[++m].rm_so >= 0)
700 else if (
match[++m].rm_so >= 0)
705 else if (
match[m+=5+1].rm_so >= 0) {
706 int i = atoi(line+
match[m].rm_so);
709 if (
match[m+=2].rm_so >= 0)
711 else if (
match[++m].rm_so >= 0)
713 else if (
match[++m].rm_so >= 0)
715 else if (
match[++m].rm_so >= 0)
717 else if (
match[++m].rm_so >= 0)
722 else if (
match[m+7].rm_so >= 0)
735 pout(
"Cannot read state file \"%s\"\n", path);
739 setmode(fileno(f), O_TEXT);
743 int good = 0, bad = 0;
745 while (fgets(line,
sizeof(line), f)) {
746 const char *
s = line + strspn(line,
" \t");
747 if (!*
s || *
s ==
'#')
757 pout(
"%s: format error\n", path);
760 pout(
"%s: %d invalid line(s) ignored\n", path, bad);
771 fprintf(f,
"%s = %" PRIu64
"\n", name, val);
777 fprintf(f,
"%s.%d.%s = %" PRIu64
"\n", name1,
id, name2, val);
784 std::string pathbak = path; pathbak +=
'~';
785 unlink(pathbak.c_str());
786 rename(path, pathbak.c_str());
790 pout(
"Cannot create state file \"%s\"\n", path);
794 fprintf(f,
"# smartd state file\n");
839 pout(
"Cannot create attribute log file \"%s\"\n", path);
844 time_t now = time(
nullptr);
846 fprintf(f,
"%d-%02d-%02d %02d:%02d:%02d;",
847 1900+tms->tm_year, 1+tms->tm_mon, tms->tm_mday,
848 tms->tm_hour, tms->tm_min, tms->tm_sec);
853 fprintf(f,
"\t%d;%d;%" PRIu64
";", pa.id, pa.val, pa.raw);
857 const char * pageNames[3] = {
"read",
"write",
"verify"};
858 for (
int k = 0; k < 3; ++k) {
861 fprintf(f,
"\t%s-corr-by-ecc-fast;%" PRIu64
";"
862 "\t%s-corr-by-ecc-delayed;%" PRIu64
";"
863 "\t%s-corr-by-retry;%" PRIu64
";"
864 "\t%s-total-err-corrected;%" PRIu64
";"
865 "\t%s-corr-algorithm-invocations;%" PRIu64
";"
866 "\t%s-gb-processed;%.3f;"
867 "\t%s-total-unc-errors;%" PRIu64
";",
873 pageNames[k], (ecp->
counter[5] / 1000000000.0),
874 pageNames[k], ecp->
counter[6]);
881 fprintf(f,
"\ttemperature;%d;", state.
temperature);
891 bool write_always =
true)
893 for (
unsigned i = 0; i < states.size(); i++) {
904 PrintOut(LOG_INFO,
"Device: %s, state written to %s\n",
913 for (
unsigned i = 0; i < states.size(); i++) {
937static void USR2handler(
int sig)
968static int capabilities_mode ;
972 if (!capabilities_mode)
974 capng_clear(CAPNG_SELECT_BOTH);
975 capng_updatev(CAPNG_ADD, (capng_type_t)(CAPNG_EFFECTIVE|CAPNG_PERMITTED),
976 CAP_SYS_ADMIN, CAP_MKNOD, CAP_SYS_RAWIO, -1);
977 if (warn_as_user && (warn_uid || warn_gid)) {
979 capng_updatev(CAPNG_ADD, (capng_type_t)(CAPNG_EFFECTIVE|CAPNG_PERMITTED),
980 CAP_SETGID, CAP_SETUID, -1);
982 if (capabilities_mode > 1) {
984 capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET,
985 CAP_SETGID, CAP_SETUID, CAP_CHOWN, CAP_FOWNER, CAP_DAC_OVERRIDE, -1);
987 capng_apply(CAPNG_SELECT_BOTH);
992 if (!capabilities_mode)
994 PrintOut(LOG_INFO,
"If mail notification does not work with '--capabilities%s\n",
995 (capabilities_mode == 1 ?
"', try '--capabilities=mail'"
996 :
"=mail', please inform " PACKAGE_BUGREPORT));
1024 void set(
const char * name,
const char * value);
1031 int size = strlen(name) + 1 + strlen(value) + 1;
1032 char * newbuf =
new char[
size];
1033 snprintf(newbuf,
size,
"%s=%s", name, value);
1036 throw std::runtime_error(
"putenv() failed");
1057 static const char *
const whichfail[] = {
1063 "FailedHealthCheck",
1064 "FailedReadSmartData",
1065 "FailedReadSmartErrorLog",
1066 "FailedReadSmartSelfTestLog",
1068 "CurrentPendingSector",
1069 "OfflineUncorrectableSector",
1075 PrintOut(LOG_CRIT,
"Internal error in MailWarning(): which=%d\n", which);
1083 days = nextdays = -1;
1086 days = nextdays = -1;
break;
1088 days = nextdays = 0;
break;
1090 days = nextdays = 1;
break;
1093 nextdays = 1 << ((unsigned)mail->
logged <= 5 ? mail->
logged : 5);
1095 days = ((unsigned)mail->
logged <= 5 ? nextdays >> 1 : nextdays);
1098 PrintOut(LOG_CRIT,
"Internal error in MailWarning(): cfg.emailfreq=%d\n", (
int)cfg.
emailfreq);
1102 time_t now = time(
nullptr);
1107 if (days > 0 && now < mail->lastsent + days * 24 * 3600)
1131 std::replace(address.begin(), address.end(),
',',
' ');
1137 env[0].
set(
"SMARTD_MAILER", executable);
1138 env[1].
set(
"SMARTD_MESSAGE", message);
1140 snprintf(dates,
sizeof(dates),
"%d", mail->
logged);
1141 env[2].
set(
"SMARTD_PREVCNT", dates);
1143 env[3].
set(
"SMARTD_TFIRST", dates);
1145 env[4].
set(
"SMARTD_TFIRSTEPOCH", dates);
1146 env[5].
set(
"SMARTD_FAILTYPE", whichfail[which]);
1147 env[6].
set(
"SMARTD_ADDRESS", address.c_str());
1148 env[7].
set(
"SMARTD_DEVICESTRING", cfg.
name.c_str());
1151 env[8].
set(
"SMARTD_DEVICETYPE",
1153 env[9].
set(
"SMARTD_DEVICE", cfg.
dev_name.c_str());
1158 snprintf(dates,
sizeof(dates),
"%d", nextdays);
1159 env[11].
set(
"SMARTD_NEXTDAYS", dates);
1161 env[12].
set(
"SMARTD_SUBJECT",
"");
1165 executable =
"<mail>";
1166 const char * newadd = (!address.empty()? address.c_str() :
"<nomailer>");
1167 const char * newwarn = (which?
"Warning via" :
"Test of");
1172 snprintf(command,
sizeof(command),
"\"%s\" 2>&1",
warning_script.c_str());
1174 snprintf(command,
sizeof(command),
"%s 2>&1",
warning_script.c_str());
1178 PrintOut(LOG_INFO,
"%s %s to %s%s ...\n",
1179 (which ?
"Sending warning via" :
"Executing test of"), executable, newadd,
1181#ifdef HAVE_POSIX_API
1184 (
unsigned)warn_uid, warn_uname.c_str(),
1185 (
unsigned)warn_gid, warn_gname.c_str() ).c_str() :
1187 warn_as_restr_user ?
" (restricted user)" :
1197#ifdef HAVE_POSIX_API
1204 pfp = popen_as_restr_user(command,
"r", warn_as_restr_user);
1206 pfp = popen(command,
"r");
1212 PrintOut(LOG_CRIT,
"%s %s to %s: failed (fork or pipe failed, or no memory) %s\n",
1213 newwarn, executable, newadd, errno?strerror(errno):
"");
1224 PrintOut(LOG_CRIT,
"%s %s to %s produced unexpected output (%s%d bytes) to STDOUT/STDERR: \n%s\n",
1225 newwarn, executable, newadd, len!=newlen?
"here truncated to ":
"", newlen,
buffer);
1233 PrintOut(LOG_CRIT,
"%s %s to %s: flushed remaining STDOUT/STDERR\n",
1234 newwarn, executable, newadd);
1236 PrintOut(LOG_CRIT,
"%s %s to %s: more than 1 MB STDOUT/STDERR flushed, breaking pipe\n",
1237 newwarn, executable, newadd);
1244#ifdef HAVE_POSIX_API
1250 status = pclose(pfp);
1254 PrintOut(LOG_CRIT,
"%s %s to %s: pclose(3) failed %s\n", newwarn, executable, newadd,
1255 errno?strerror(errno):
"");
1258 if (WIFEXITED(status)) {
1260 int status8 = WEXITSTATUS(status);
1262 PrintOut(LOG_CRIT,
"%s %s to %s: failed (32-bit/8-bit exit status: %d/%d) perhaps caught signal %d [%s]\n",
1263 newwarn, executable, newadd, status, status8, status8-128, strsignal(status8-128));
1265 PrintOut(LOG_CRIT,
"%s %s to %s: failed (32-bit/8-bit exit status: %d/%d)\n",
1266 newwarn, executable, newadd, status, status8);
1270 PrintOut(LOG_INFO,
"%s %s to %s: successful\n", newwarn, executable, newadd);
1273 if (WIFSIGNALED(status))
1274 PrintOut(LOG_INFO,
"%s %s to %s: exited because of uncaught signal %d [%s]\n",
1275 newwarn, executable, newadd, WTERMSIG(status), strsignal(WTERMSIG(status)));
1279 if (WIFSTOPPED(status))
1280 PrintOut(LOG_CRIT,
"%s %s to %s: process STOPPED because it caught signal %d [%s]\n",
1281 newwarn, executable, newadd, WSTOPSIG(status), strsignal(WSTOPSIG(status)));
1310 PrintOut(LOG_INFO,
"Device: %s, %s, warning condition reset after %d email%s\n", cfg.
name.c_str(),
1322static
void vsyslog_lines(
int priority, const
char *
fmt, va_list
ap)
1327 for (
char * p = buf, * q; p && *p; p = q) {
1328 if ((q = strchr(p,
'\n')))
1331 syslog(priority,
"%s\n", p);
1337#define vsyslog_lines vsyslog
1361 vfprintf(f,
fmt,
ap);
1366 openlog(
"smartd", LOG_PID,
facility);
1367 vsyslog_lines(LOG_INFO,
fmt,
ap);
1388 vfprintf(f,
fmt,
ap);
1392 openlog(
"smartd", LOG_PID,
facility);
1393 vsyslog_lines(priority,
fmt,
ap);
1403 pout(
"Warning! %s error: invalid SMART checksum.\n",
string);
1412 int waited, max_wait = 10;
1413 struct stat stat_buf;
1418 for(waited = 0; waited < max_wait; ++waited) {
1419 if (!stat(
pid_file.c_str(), &stat_buf)) {
1443 if ((pid=fork()) < 0) {
1445 PrintOut(LOG_CRIT,
"smartd unable to fork daemon process!\n");
1461 if ((pid=fork()) < 0) {
1463 PrintOut(LOG_CRIT,
"smartd unable to fork daemon process!\n");
1474 int open_max = sysconf(_SC_OPEN_MAX);
1475#ifdef HAVE_CLOSE_RANGE
1476 if (close_range(0, open_max - 1, 0))
1481 for (
int i = 0, failed = 0; i < open_max && failed < 1024; i++)
1482 failed = (!close(i) ? 0 : failed + 1);
1486 int fd = open(
"/dev/null", O_RDWR);
1487 if (!(fd == 0 && dup(fd) == 1 && dup(fd) == 2 && !chdir(
"/"))) {
1488 PrintOut(LOG_CRIT,
"smartd unable to redirect to /dev/null or to chdir to root!\n");
1494 PrintOut(LOG_INFO,
"smartd has fork()ed into background mode. New PID=%d.\n", (
int)getpid());
1501 if (daemon_detach(
"smartd")) {
1502 PrintOut(LOG_CRIT,
"smartd unable to detach from console!\n");
1517 pid_t pid = getpid();
1520 old_umask = umask(0077);
1523 old_umask = umask(0033);
1528 if (!(f && fprintf(f,
"%d\n", (
int)pid) > 0 && f.
close())) {
1529 PrintOut(LOG_CRIT,
"unable to write PID file %s - exiting.\n",
pid_file.c_str());
1532 PrintOut(LOG_INFO,
"file %s written containing PID %d\n",
pid_file.c_str(), (
int)pid);
1547 "Configuration file (%s) Directives (after device name):\n"
1548 " -d TYPE Set the device type: auto, ignore, removable,\n"
1550 " -T TYPE Set the tolerance to one of: normal, permissive\n"
1551 " -o VAL Enable/disable automatic offline tests (on/off)\n"
1552 " -S VAL Enable/disable attribute autosave (on/off)\n"
1553 " -n MODE No check if: never, sleep[,N][,q], standby[,N][,q], idle[,N][,q]\n"
1554 " -H Monitor SMART Health Status, report if failed\n"
1555 " -s REG Do Self-Test at time(s) given by regular expression REG\n"
1556 " -l TYPE Monitor SMART log or self-test status:\n"
1557 " error, selftest, xerror, offlinests[,ns], selfteststs[,ns]\n"
1558 " -l scterc,R,W Set SCT Error Recovery Control\n"
1559 " -e Change device setting: aam,[N|off], apm,[N|off], dsn,[on|off],\n"
1560 " lookahead,[on|off], security-freeze, standby,[N|off], wcache,[on|off]\n"
1561 " -f Monitor 'Usage' Attributes, report failures\n"
1562 " -m ADD Send email warning to address ADD\n"
1563 " -M TYPE Modify email warning behavior (see man page)\n"
1564 " -p Report changes in 'Prefailure' Attributes\n"
1565 " -u Report changes in 'Usage' Attributes\n"
1566 " -t Equivalent to -p and -u Directives\n"
1567 " -r ID Also report Raw values of Attribute ID with -p, -u or -t\n"
1568 " -R ID Track changes in Attribute ID Raw value with -p, -u or -t\n"
1569 " -i ID Ignore Attribute ID for -f Directive\n"
1570 " -I ID Ignore Attribute ID for -p, -u or -t Directive\n"
1571 " -C ID[+] Monitor [increases of] Current Pending Sectors in Attribute ID\n"
1572 " -U ID[+] Monitor [increases of] Offline Uncorrectable Sectors in Attribute ID\n"
1573 " -W D,I,C Monitor Temperature D)ifference, I)nformal limit, C)ritical limit\n"
1574 " -v N,ST Modifies labeling of Attribute N (see man page) \n"
1575 " -P TYPE Drive-specific presets: use, ignore, show, showall\n"
1576 " -a Default: -H -f -t -l error -l selftest -l selfteststs -C 197 -U 198\n"
1577 " -F TYPE Use firmware bug workaround:\n"
1579 " -c i=N Set interval between disk checks to N seconds\n"
1580 " # Comment: text after a hash sign is ignored\n"
1581 " \\ Line continuation character\n"
1582 "Attribute ID is a decimal integer 1 <= ID <= 255\n"
1583 "Use ID = 0 to turn off -C and/or -U Directives\n"
1584 "Example: /dev/sda -a\n",
1586 smi()->get_valid_dev_types_str().c_str(),
1597 return "<PATH_PREFIX>, -";
1599 return "[+]<FILE_NAME>";
1601 return "<FILE_NAME>, -";
1603 return "daemon, local0, local1, local2, local3, local4, local5, local6, local7";
1605 return "nodev[0], errors[,nodev0], nodev[0]startup, never, onecheck, showtests";
1607 return "ioctl[,N], ataioctl[,N], scsiioctl[,N], nvmeioctl[,N]";
1610 return "<FILE_NAME>";
1612 return "<INTEGER_SECONDS>";
1613#ifdef HAVE_POSIX_API
1615 return "<USER>[:<GROUP>], -";
1616#elif defined(_WIN32)
1618 return "restricted, unchanged";
1620#ifdef HAVE_LIBCAP_NG
1622 return "mail, <no_argument>";
1632 PrintOut(LOG_INFO,
"Usage: smartd [options]\n\n");
1633#ifdef SMARTMONTOOLS_ATTRIBUTELOG
1634 PrintOut(LOG_INFO,
" -A PREFIX|-, --attributelog=PREFIX|-\n");
1636 PrintOut(LOG_INFO,
" -A PREFIX, --attributelog=PREFIX\n");
1638 PrintOut(LOG_INFO,
" Log attribute information to {PREFIX}MODEL-SERIAL.TYPE.csv\n");
1639#ifdef SMARTMONTOOLS_ATTRIBUTELOG
1640 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_ATTRIBUTELOG
"MODEL-SERIAL.TYPE.csv]\n");
1643 PrintOut(LOG_INFO,
" -B [+]FILE, --drivedb=[+]FILE\n");
1644 PrintOut(LOG_INFO,
" Read and replace [add] drive database from FILE\n");
1646#ifdef SMARTMONTOOLS_DRIVEDBDIR
1648 PrintOut(LOG_INFO,
" and then %s", get_drivedb_path_default());
1651 PrintOut(LOG_INFO,
" -c NAME|-, --configfile=NAME|-\n");
1652 PrintOut(LOG_INFO,
" Read configuration file NAME or stdin\n");
1654#ifdef HAVE_LIBCAP_NG
1655 PrintOut(LOG_INFO,
" -C, --capabilities[=mail]\n");
1656 PrintOut(LOG_INFO,
" Drop unneeded Linux process capabilities.\n"
1657 " Warning: Mail notification may not work when used.\n\n");
1659 PrintOut(LOG_INFO,
" -d, --debug\n");
1660 PrintOut(LOG_INFO,
" Start smartd in debug mode\n\n");
1661 PrintOut(LOG_INFO,
" -D, --showdirectives\n");
1662 PrintOut(LOG_INFO,
" Print the configuration file Directives and exit\n\n");
1663 PrintOut(LOG_INFO,
" -h, --help, --usage\n");
1664 PrintOut(LOG_INFO,
" Display this help and exit\n\n");
1665 PrintOut(LOG_INFO,
" -i N, --interval=N\n");
1666 PrintOut(LOG_INFO,
" Set interval between disk checks to N seconds, where N >= 10\n\n");
1667 PrintOut(LOG_INFO,
" -l local[0-7], --logfacility=local[0-7]\n");
1669 PrintOut(LOG_INFO,
" Use syslog facility local0 - local7 or daemon [default]\n\n");
1671 PrintOut(LOG_INFO,
" Log to \"./smartd.log\", stdout, stderr [default is event log]\n\n");
1674 PrintOut(LOG_INFO,
" -n, --no-fork\n");
1675 PrintOut(LOG_INFO,
" Do not fork into background\n");
1676#ifdef HAVE_LIBSYSTEMD
1677 PrintOut(LOG_INFO,
" (systemd 'Type=notify' is assumed if $NOTIFY_SOCKET is set)\n");
1681 PrintOut(LOG_INFO,
" -p NAME, --pidfile=NAME\n");
1682 PrintOut(LOG_INFO,
" Write PID file NAME\n\n");
1683 PrintOut(LOG_INFO,
" -q WHEN, --quit=WHEN\n");
1685 PrintOut(LOG_INFO,
" -r, --report=TYPE\n");
1687#ifdef SMARTMONTOOLS_SAVESTATES
1688 PrintOut(LOG_INFO,
" -s PREFIX|-, --savestates=PREFIX|-\n");
1690 PrintOut(LOG_INFO,
" -s PREFIX, --savestates=PREFIX\n");
1692 PrintOut(LOG_INFO,
" Save disk states to {PREFIX}MODEL-SERIAL.TYPE.state\n");
1693#ifdef SMARTMONTOOLS_SAVESTATES
1694 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_SAVESTATES
"MODEL-SERIAL.TYPE.state]\n");
1697 PrintOut(LOG_INFO,
" -w NAME, --warnexec=NAME\n");
1698 PrintOut(LOG_INFO,
" Run executable NAME on warnings\n");
1700 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_SMARTDSCRIPTDIR
"/smartd_warning.sh]\n\n");
1704#ifdef HAVE_POSIX_API
1705 PrintOut(LOG_INFO,
" -u USER[:GROUP], --warn-as-user=USER[:GROUP]\n");
1706 PrintOut(LOG_INFO,
" Run warning script as non-privileged USER\n\n");
1707#elif defined(_WIN32)
1708 PrintOut(LOG_INFO,
" -u MODE, --warn-as-user=MODE\n");
1713 PrintOut(LOG_INFO,
" Running as windows service (see man page), install with:\n");
1714 PrintOut(LOG_INFO,
" smartd install [options]\n");
1715 PrintOut(LOG_INFO,
" Remove service with:\n");
1716 PrintOut(LOG_INFO,
" smartd remove\n\n");
1718 PrintOut(LOG_INFO,
" -V, --version, --license, --copyright\n");
1719 PrintOut(LOG_INFO,
" Print License, Copyright, and version information\n");
1724 if (!device->
close()){
1735 bool changed =
false;
1736 for (
unsigned i = 0; i <
s.size(); i++) {
1740 if ((
' ' <= c && c <=
'~') && !(i == 0 && c ==
'~'))
1751 return !( (
'0' <= c && c <=
'9')
1752 || (
'A' <= c && c <=
'Z')
1753 || (
'a' <= c && c <=
'z'));
1764 PrintOut(LOG_INFO,
"Device: %s, Read Summary SMART Error Log failed\n",name);
1772 PrintOut(LOG_INFO,
"Device: %s, Read Extended Comprehensive SMART Error Log failed\n",name);
1790 PrintOut(LOG_INFO,
"Device: %s, Read SMART Self Test Log Failed\n",name);
1800 for (
int i = 20; i >= 0; i--) {
1806 int status =
entry.selfteststatus >> 4;
1807 if (status == 0x0 && (
entry.selftestnumber & 0x7f) == 0x02)
1811 if (0x3 <= status && status <= 0x8) {
1816 hour =
entry.timestamp;
1826 return ((status & 0x7f) == 0x03);
1832 return ((status >> 4) == 0xf);
1839 switch (status & 0x7f) {
1840 case 0x00: msg =
"was never started";
break;
1841 case 0x02: msg =
"was completed without error";
break;
1842 case 0x03: msg =
"is in progress";
break;
1843 case 0x04: msg =
"was suspended by an interrupting command from host";
break;
1844 case 0x05: msg =
"was aborted by an interrupting command from host";
break;
1845 case 0x06: msg =
"was aborted by the device with a fatal error";
break;
1846 default: msg =
nullptr;
1850 PrintOut(((status & 0x7f) == 0x06 ? LOG_CRIT : LOG_INFO),
1851 "Device: %s, offline data collection %s%s\n", name, msg,
1852 ((status & 0x80) ?
" (auto:on)" :
""));
1854 PrintOut(LOG_INFO,
"Device: %s, unknown offline data collection status 0x%02x\n",
1862 switch (status >> 4) {
1863 case 0x0: msg =
"completed without error";
break;
1864 case 0x1: msg =
"was aborted by the host";
break;
1865 case 0x2: msg =
"was interrupted by the host with a reset";
break;
1866 case 0x3: msg =
"could not complete due to a fatal or unknown error";
break;
1867 case 0x4: msg =
"completed with error (unknown test element)";
break;
1868 case 0x5: msg =
"completed with error (electrical test element)";
break;
1869 case 0x6: msg =
"completed with error (servo/seek test element)";
break;
1870 case 0x7: msg =
"completed with error (read test element)";
break;
1871 case 0x8: msg =
"completed with error (handling damage?)";
break;
1872 default: msg =
nullptr;
1876 PrintOut(((status >> 4) >= 0x4 ? LOG_CRIT : LOG_INFO),
1877 "Device: %s, previous self-test %s\n", name, msg);
1878 else if ((status >> 4) == 0xf)
1879 PrintOut(LOG_INFO,
"Device: %s, self-test in progress, %u0%% remaining\n",
1880 name, status & 0x0f);
1882 PrintOut(LOG_INFO,
"Device: %s, unknown self-test status 0x%02x\n",
1888 unsigned char id,
const char * msg)
1893 PrintOut(LOG_INFO,
"Device: %s, can't monitor %s count - no Attribute %d\n",
1894 cfg.
name.c_str(), msg,
id);
1902 PrintOut(LOG_INFO,
"Device: %s, ignoring %s count - bogus Attribute %d value %" PRIu64
" (0x%" PRIx64
")\n",
1903 cfg.
name.c_str(), msg,
id, rawval, rawval);
1929 int set_option = 0,
bool has_value =
false)
1936 else if (set_option < 0)
1940 else if (set_option > 0)
1950 for (
const auto & prev_cfg : prev_cfgs) {
1951 if (!prev_cfg.id_is_unique)
1956 || (!prev_cfg.dev_idinfo_bc.empty() && cfg.
dev_idinfo == prev_cfg.dev_idinfo_bc)))
1959 PrintOut(LOG_INFO,
"Device: %s, same identity as %s, ignored\n",
1960 cfg.
dev_name.c_str(), prev_cfg.dev_name.c_str());
1976 const char *name = cfg.
name.c_str();
1985 PrintOut(LOG_INFO,
"Device: %s, not ATA, no IDENTIFY DEVICE Structure\n",name);
1987 PrintOut(LOG_INFO,
"Device: %s, packet devices [this device %s] not SMART capable\n",
1994 char model[40+1], serial[20+1], firmware[8+1];
2004 char wwn[64]; wwn[0] = 0;
2005 unsigned oui = 0; uint64_t unique_id = 0;
2008 snprintf(wwn,
sizeof(wwn),
"WWN:%x-%06x-%09" PRIx64
", ", naa, oui, unique_id);
2029 PrintOut(LOG_INFO,
"Device: %s, smartd database not searched (Directive: -P ignore).\n", name);
2032 std::string dbversion;
2036 PrintOut(LOG_INFO,
"Device: %s, not found in smartd database%s%s.\n", name,
2037 (!dbversion.empty() ?
" " :
""), (!dbversion.empty() ? dbversion.c_str() :
""));
2039 PrintOut(LOG_INFO,
"Device: %s, found in smartd database%s%s%s%s\n",
2040 name, (!dbversion.empty() ?
" " :
""), (!dbversion.empty() ? dbversion.c_str() :
""),
2049 bool locked = ((word128 & 0x0007) == 0x0007);
2051 PrintOut(LOG_INFO,
"Device: %s, ATA Security is **LOCKED**\n", name);
2063 PrintOut(LOG_INFO,
"Device %s: presets are:\n", name);
2075 PrintOut(LOG_INFO,
"Device: %s, lacks SMART capability\n",name);
2078 PrintOut(LOG_INFO,
"Device: %s, ATA IDENTIFY DEVICE words 82-83 don't specify if SMART capable.\n",name);
2082 PrintOut(LOG_INFO,
"Device: %s, proceeding since '-T permissive' Directive given.\n",name);
2085 PrintOut(LOG_INFO,
"Device: %s, to proceed anyway, use '-T permissive' Directive.\n",name);
2093 PrintOut(LOG_INFO,
"Device: %s, could not enable SMART capability\n",name);
2097 PrintOut(LOG_INFO,
"Device: %s, to proceed anyway, use '-T permissive' Directive.\n", name);
2101 PrintOut(LOG_INFO,
"Device: %s, proceeding since '-T permissive' Directive given.\n", name);
2104 PrintOut(LOG_INFO,
"Device: %s, proceeding since SMART is already enabled\n", name);
2111 PrintOut(LOG_INFO,
"Device: %s, could not disable SMART Attribute Autosave.\n",name);
2113 PrintOut(LOG_INFO,
"Device: %s, disabled SMART Attribute Autosave.\n",name);
2119 PrintOut(LOG_INFO,
"Device: %s, could not enable SMART Attribute Autosave.\n",name);
2121 PrintOut(LOG_INFO,
"Device: %s, enabled SMART Attribute Autosave.\n",name);
2126 PrintOut(LOG_INFO,
"Device: %s, not capable of SMART Health Status check\n",name);
2137 bool smart_val_ok =
false;
2146 PrintOut(LOG_INFO,
"Device: %s, Read SMART Values failed\n", name);
2152 smart_val_ok =
true;
2154 PrintOut(LOG_INFO,
"Device: %s, Read SMART Thresholds failed%s\n",
2155 name, (cfg.
usagefailed ?
", ignoring -f Directive" :
""));
2166 "Current_Pending_Sector"))
2171 "Offline_Uncorrectable"))
2176 PrintOut(LOG_INFO,
"Device: %s, can't monitor Temperature, ignoring -W %d,%d,%d\n",
2182 for (
int id = 1;
id <= 255;
id++) {
2190 PrintOut(LOG_INFO,
"Device: %s, no Attribute %d, ignoring -%c %d%s\n", name,
id, opt,
id, excl);
2193 if (!((prefail && cfg.
prefail) || (!prefail && cfg.
usage)))
2194 PrintOut(LOG_INFO,
"Device: %s, not monitoring %s Attributes, ignoring -%c %d%s\n", name,
2195 (prefail ?
"Prefailure" :
"Usage"), opt,
id, excl);
2206 PrintOut(LOG_INFO,
"Device: %s, could not %s SMART Automatic Offline Testing.\n",name, what);
2210 PrintOut(LOG_INFO,
"Device: %s, SMART Automatic Offline Testing unsupported...\n",name);
2213 PrintOut(LOG_INFO,
"Device: %s, %s SMART Automatic Offline Testing failed.\n", name, what);
2215 PrintOut(LOG_INFO,
"Device: %s, %sd SMART Automatic Offline Testing.\n", name, what);
2221 bool smart_logdir_ok =
false, gp_logdir_ok =
false;
2227 smart_logdir_ok =
true;
2232 gp_logdir_ok =
true;
2238 int errcnt = 0;
unsigned hour = 0;
2242 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test Log, ignoring -l selftest (override with -T permissive)\n", name);
2246 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test Log, ignoring -l selftest\n", name);
2262 PrintOut(LOG_INFO,
"Device: %s, no SMART Error Log, ignoring -l error (override with -T permissive)\n", name);
2266 PrintOut(LOG_INFO,
"Device: %s, no SMART Error Log, ignoring -l error\n", name);
2277 PrintOut(LOG_INFO,
"Device: %s, no Extended Comprehensive SMART Error Log, ignoring -l xerror (override with -T permissive)\n",
2282 PrintOut(LOG_INFO,
"Device: %s, no Extended Comprehensive SMART Error Log, ignoring -l xerror\n", name);
2286 PrintOut(LOG_INFO,
"Device: %s, SMART Error Logs report different error counts: %d != %d\n",
2300 PrintOut(LOG_INFO,
"Device: %s, no SMART Offline Data Collection capability, ignoring -l offlinests (override with -T permissive)\n", name);
2302 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test capability, ignoring -l selfteststs (override with -T permissive)\n", name);
2311 if (-1 == powermode) {
2312 PrintOut(LOG_CRIT,
"Device: %s, no ATA CHECK POWER STATUS support, ignoring -n Directive\n", name);
2315 else if (powermode!=0x00 && powermode!=0x01
2316 && powermode!=0x40 && powermode!=0x41
2317 && powermode!=0x80 && powermode!=0x81 && powermode!=0x82 && powermode!=0x83
2318 && powermode!=0xff) {
2319 PrintOut(LOG_CRIT,
"Device: %s, CHECK POWER STATUS returned %d, not ATA compliant, ignoring -n Directive\n",
2361 PrintOut(LOG_INFO,
"Device: %s, ATA settings applied: %s\n", name, msg.c_str());
2366 PrintOut(LOG_INFO,
"Device: %s, no SCT Error Recovery Control support, ignoring -l scterc\n",
2369 PrintOut(LOG_INFO,
"Device: %s, no SCT support if ATA Security is LOCKED, ignoring -l scterc\n",
2373 PrintOut(LOG_INFO,
"Device: %s, set of SCT Error Recovery Control failed\n", name);
2375 PrintOut(LOG_INFO,
"Device: %s, SCT Error Recovery Control set to: Read: %u, Write: %u\n",
2390 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n",name);
2403 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", name, cfg.
state_file.c_str());
2422 int err, req_len, avail_len, version, len;
2423 const char *device = cfg.
name.c_str();
2427 uint8_t vpdBuf[252];
2428 char lu_id[64], serial[256], vendor[40], model[40];
2431 memset(inqBuf, 0, 96);
2438 PrintOut(LOG_INFO,
"Device: %s, Both 36 and 64 byte INQUIRY failed; "
2439 "skip device [err=%d, %d]\n", device, err, err64);
2443 version = (inqBuf[2] & 0x7f);
2445 avail_len = inqBuf[4] + 5;
2446 len = (avail_len < req_len) ? avail_len : req_len;
2448 PrintOut(LOG_INFO,
"Device: %s, INQUIRY response less than 36 bytes; "
2449 "skip device\n", device);
2453 int pdt = inqBuf[0] & 0x1f;
2464 PrintOut(LOG_INFO,
"Device: %s, not a disk like device [PDT=0x%x], "
2465 "skip\n", device, pdt);
2476 if (version >= 0x3) {
2479 vpdBuf,
sizeof(vpdBuf))) {
2486 vpdBuf,
sizeof(vpdBuf))) {
2488 vpdBuf[4 + len] =
'\0';
2503 (
char *)&inqBuf[8], (
char *)&inqBuf[16], (
char *)&inqBuf[32],
2504 (lu_id[0] ?
", lu id: " :
""), (lu_id[0] ? lu_id :
""),
2505 (serial[0] ?
", S/N: " :
""), (serial[0] ? serial :
""),
2506 (si_str[0] ?
", " :
""), (si_str[0] ? si_str :
""));
2526 PrintOut(LOG_INFO,
"Device: %s, NOT READY (e.g. spun down); skip device\n", device);
2528 PrintOut(LOG_INFO,
"Device: %s, NO MEDIUM present; skip device\n", device);
2530 PrintOut(LOG_INFO,
"Device: %s, BECOMING (but not yet) READY; skip device\n", device);
2532 PrintOut(LOG_CRIT,
"Device: %s, failed Test Unit Ready [err=%d]\n", device, err);
2549 "Device: %s, Bad IEC (SMART) mode page, err=%d, skip device\n",
2558 PrintOut(LOG_INFO,
"Device: %s, IE (SMART) not enabled, skip device\n"
2559 "Try 'smartctl -s on %s' to turn on SMART features\n",
2601 uint8_t currenttemp = 0;
2602 uint8_t triptemp = 0;
2605 &asc, &ascq, ¤ttemp, &triptemp)) {
2606 PrintOut(LOG_INFO,
"Device: %s, unexpectedly failed to read SMART values\n", device);
2611 PrintOut(LOG_INFO,
"Device: %s, can't monitor Temperature, ignoring -W %d,%d,%d\n",
2622 PrintOut(LOG_INFO,
"Device: %s, does not support SMART Self-Test Log.\n", device);
2637 PrintOut(LOG_INFO,
"Device: %s, could not disable autosave (set GLTSD bit).\n",device);
2639 PrintOut(LOG_INFO,
"Device: %s, disabled autosave (set GLTSD bit).\n",device);
2645 PrintOut(LOG_INFO,
"Device: %s, could not enable autosave (clear GLTSD bit).\n",device);
2647 PrintOut(LOG_INFO,
"Device: %s, enabled autosave (cleared GLTSD bit).\n",device);
2651 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n", device);
2670 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", device, cfg.
state_file.c_str());
2687 for (
int i = 8; i < 16; i++) {
2689 return ~(uint64_t)0;
2691 uint64_t lo = val[7];
2692 for (
int i = 7-1; i >= 0; i--) {
2693 lo <<= 8; lo += val[i];
2700 uint64_t newcnt = 0)
2704 unsigned want_entries = 64;
2711 if (!read_entries) {
2712 PrintOut(LOG_INFO,
"Device: %s, Read %u entries from Error Information Log failed\n",
2713 cfg.
name.c_str(), want_entries);
2722 int err = 0, ign = 0;
2723 for (
unsigned i = 0; i < read_entries; i++) {
2743 PrintOut(LOG_INFO,
"Device: %s, NVMe error [%u], count %" PRIu64
", status 0x%04x: %s\n",
2748 std::string msg =
strprintf(
"Device: %s, NVMe error count increased from %" PRIu64
" to %" PRIu64
2749 " (%d new, %d ignored, %" PRIu64
" unknown)",
2750 cfg.
name.c_str(), oldcnt, newcnt, err, ign,
2751 (mincnt > oldcnt + 1 ? mincnt - oldcnt - 1 : 0));
2754 PrintOut(LOG_INFO,
"%s\n", msg.c_str());
2757 PrintOut(LOG_CRIT,
"%s\n", msg.c_str());
2769 const char *name = cfg.
name.c_str();
2776 PrintOut(LOG_INFO,
"Device: %s, NVMe Identify Controller failed\n", name);
2782 char model[40+1], serial[20+1], firmware[8+1];
2788 char nsstr[32] =
"", capstr[32] =
"";
2791 snprintf(nsstr,
sizeof(nsstr),
", NSID:%u",
nsid);
2798 cfg.*idinfo =
strprintf(
"%s, S/N:%s, FW:%s%s%s%s", model, serial, firmware,
2799 nsstr, (capstr[0] ?
", " :
""), capstr);
2800 if (!(nsstr[0] && id_ctrl.
nn == 1))
2823 PrintOut(LOG_INFO,
"Device: %s, failed to read NVMe SMART/Health Information\n", name);
2831 PrintOut(LOG_INFO,
"Device: %s, no Temperature sensors, ignoring -W %d,%d,%d\n",
2841 PrintOut(LOG_INFO,
"Device: %s, Error Information unavailable, ignoring -l [x]error\n", name);
2855 PrintOut(LOG_INFO,
"Device: %s, Read NVMe Self-test Log failed: %s\n", name,
2860 PrintOut(LOG_INFO,
"Device: %s, does not support NVMe Self-tests, ignoring%s%s%s%s\n", name,
2861 (cfg.
selftest ?
" -l selftest" :
""),
2877 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n", name);
2894 snprintf(nsstr,
sizeof(nsstr),
"-n%u",
nsid);
2898 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", name, cfg.
state_file.c_str());
2910 const char * name = cfg.
name.c_str();
2914 MailWarning(cfg, state, 0,
"TEST EMAIL from smartd for device: %s", name);
2929 PrintOut(LOG_INFO,
"Device: %s, is in %s mode, suspending checks\n", name,
"STANDBY (OS)");
2940 if (!device->
open()) {
2943 PrintOut(LOG_INFO,
"Device: %s, open() of %s device failed: %s\n", name, type, device->
get_errmsg());
2944 MailWarning(cfg, state, 9,
"Device: %s, unable to open %s device", name, type);
2947 PrintOut(LOG_INFO,
"Device: %s, removed %s device: %s\n", name, type, device->
get_errmsg());
2951 PrintOut(LOG_INFO,
"Device: %s, %s device still removed: %s\n", name, type, device->
get_errmsg());
2956 PrintOut(LOG_INFO,
"Device: %s, opened %s device\n", name, type);
2961 PrintOut(LOG_INFO,
"Device: %s, reconnected %s device\n", name, type);
2971 int errcnt, uint64_t hour)
2973 const char * name = cfg.
name.c_str();
2978 MailWarning(cfg, state, 8,
"Device: %s, Read SMART Self-Test Log Failed", name);
2984 PrintOut(LOG_CRIT,
"Device: %s, Self-Test Log error count increased from %d to %d\n",
2986 MailWarning(cfg, state, 3,
"Device: %s, Self-Test Log error count increased from %d to %d",
2990 else if (errcnt > 0 && state.
selfloghour != hour) {
2998 PrintOut(LOG_CRIT,
"Device: %s, new Self-Test Log error at hour timestamp %" PRIu64
"\n",
3000 MailWarning(cfg, state, 3,
"Device: %s, new Self-Test Log error at hour timestamp %" PRIu64
"\n",
3008 PrintOut(LOG_INFO,
"Device: %s, Self-Test Log error count decreased from %d to %d\n",
3043 time_t now = (!usetime ? time(
nullptr) : usetime);
3057 unsigned offsets[max_offsets] = {0, }, limits[max_offsets] = {0, };
3058 unsigned num_offsets = 1;
3060 const char * q = strchr(p,
':');
3064 unsigned offset = 0, limit = 0;
int n1 = -1, n2 = -1, n3 = -1;
3065 sscanf(p,
"%u%n-%n%u%n", &offset, &n1, &n2, &limit, &n3);
3066 if (!(n1 == 3 && (n2 < 0 || (n3 == 3+1+3 && limit > 0))))
3068 offsets[num_offsets] = offset; limits[num_offsets] = limit;
3070 p += (n3 > 0 ? n3 : n1);
3075 time_t testtime = 0;
int testhour = 0;
3080 for (
unsigned i = 0; i < num_offsets; i++) {
3081 unsigned offset = offsets[i], limit = limits[i];
3083 if (0 < limit && limit < delay)
3088 int weekday = (tms->tm_wday ? tms->tm_wday : 7);
3089 for (
int j = 0; j <= maxtest; j++) {
3102 snprintf(pattern,
sizeof(pattern),
"%c/%02d/%02d/%1d/%02d",
3103 test_type_chars[j], tms->tm_mon+1, tms->tm_mday, weekday, tms->tm_hour);
3105 const unsigned len =
sizeof(
"S/01/01/1/01") - 1;
3106 snprintf(pattern + len,
sizeof(pattern) - len,
":%03u", offset);
3108 snprintf(pattern + len + 4,
sizeof(pattern) - len - 4,
"-%03u", limit);
3112 testtype = pattern[0];
3113 testtime = t; testhour = tms->tm_hour;
3127 if ((t += 3600) > now)
3138 if (!usetime && !(testhour == tmnow->tm_hour && testtime + 3600 > now)) {
3140 PrintOut(LOG_INFO,
"Device: %s, old test of type %c not run at %s, starting now.\n",
3141 cfg.
name.c_str(), testtype, datebuf);
3151 unsigned numdev = configs.size();
3156 PrintOut(LOG_INFO,
"\nNext scheduled self tests (at most 5 of each type per device):\n");
3159 time_t now = time(
nullptr);
3166 time_t testtime = now + seconds;
3167 for (
unsigned i = 0; i < numdev; i++) {
3177 PrintOut(LOG_INFO,
"Device: %s, will do test %d of type %c at %s\n", cfg.
name.c_str(),
3186 PrintOut(LOG_INFO,
"\nTotals [%s - %s]:\n", datenow, date);
3187 for (
unsigned i = 0; i < numdev; i++) {
3189 bool ata =
devices.at(i)->is_ata();
3194 PrintOut(LOG_INFO,
"Device: %s, will do %3d test%s of type %c\n", cfg.
name.c_str(),
3206 const char *testname =
nullptr;
3207 const char *name = cfg.
name.c_str();
3211 PrintOut(LOG_CRIT,
"Device: %s, does not support Self-Tests\n", name);
3216 if (1 == inProgress) {
3217 PrintOut(LOG_INFO,
"Device: %s, skip since Self-Test already in "
3218 "progress.\n", name);
3224 testname =
"Short Self";
3228 testname =
"Long Self";
3234 PrintOut(LOG_CRIT,
"Device: %s, not capable of %c Self-Test\n", name,
3241 PrintOut(LOG_CRIT,
"Device: %s, not capable of %s-Test\n", name,
3250 PrintOut(LOG_CRIT,
"Device: %s, execute %s-Test failed (err: %d)\n", name,
3255 PrintOut(LOG_INFO,
"Device: %s, starting scheduled %s-Test.\n", name, testname);
3264 const char *name = cfg.
name.c_str();
3270 PrintOut(LOG_CRIT,
"Device: %s, not capable of Offline or Self-Testing.\n", name);
3275 int dotest = -1, mode = 0;
3276 const char *testname =
nullptr;
3279 testname=
"Offline Immediate ";
3286 testname=
"Conveyance Self-";
3293 testname=
"Short Self-";
3300 testname=
"Long Self-";
3307 case 'c':
case 'n':
case 'r':
3308 testname =
"Selective Self-";
3324 PrintOut(LOG_CRIT,
"Device: %s, not capable of %sTest\n", name, testname);
3329 if (15==(
data.self_test_exec_status >> 4)) {
3331 PrintOut(LOG_INFO,
"Device: %s, will not skip scheduled %sTest "
3332 "despite unclear Self-Test byte (SAMSUNG Firmware bug).\n", name, testname);
3334 PrintOut(LOG_INFO,
"Device: %s, skip scheduled %sTest; %1d0%% remaining of current Self-Test.\n",
3335 name, testname, (
int)(
data.self_test_exec_status & 0x0f));
3349 PrintOut(LOG_CRIT,
"Device: %s, prepare %sTest failed\n", name, testname);
3353 PrintOut(LOG_INFO,
"Device: %s, %s test span at LBA %" PRIu64
" - %" PRIu64
" (%" PRIu64
" sectors, %u%% - %u%% of disk).\n",
3355 start, end, end - start + 1,
3365 PrintOut(LOG_CRIT,
"Device: %s, execute %sTest failed.\n", name, testname);
3371 if (testtype ==
'O')
3376 PrintOut(LOG_INFO,
"Device: %s, starting scheduled %sTest.\n", name, testname);
3382 unsigned char id,
bool increase_only,
3384 int mailtype,
const char * msg)
3400 if (!(!increase_only || prev_rawval < rawval))
3404 std::string
s =
strprintf(
"Device: %s, %" PRId64
" %s", cfg.
name.c_str(), rawval, msg);
3405 if (prev_rawval > 0 && rawval != prev_rawval)
3406 s +=
strprintf(
" (changed %+" PRId64
")", rawval - prev_rawval);
3414static const char *
fmt_temp(
unsigned char x,
char (& buf)[20])
3418 snprintf(buf,
sizeof(buf),
"%u", x);
3425 if (!(0 < currtemp && currtemp < 255)) {
3426 PrintOut(LOG_INFO,
"Device: %s, failed to read Temperature\n", cfg.
name.c_str());
3431 const char * minchg =
"", * maxchg =
"";
3432 if (currtemp > state.
tempmax) {
3445 PrintOut(LOG_INFO,
"Device: %s, initial Temperature is %d Celsius (Min/Max %s/%u%s)\n",
3448 PrintOut(LOG_INFO,
" [trip Temperature is %d Celsius]\n", (
int)triptemp);
3472 PrintOut(LOG_INFO,
"Device: %s, Temperature changed %+d Celsius to %u Celsius (Min/Max %s%s/%u%s)\n",
3480 PrintOut(LOG_CRIT,
"Device: %s, Temperature %u Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)\n",
3482 MailWarning(cfg, state, 12,
"Device: %s, Temperature %d Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)",
3486 PrintOut(LOG_INFO,
"Device: %s, Temperature %u Celsius reached limit of %u Celsius (Min/Max %s%s/%u%s)\n",
3491 if (currtemp < limit)
3492 reset_warning_mail(cfg, state, 12,
"Temperature %u Celsius dropped below %u Celsius", currtemp, limit);
3512 PrintOut(LOG_CRIT,
"Device: %s, Failed SMART usage Attribute: %d %s.\n", cfg.
name.c_str(), attr.
id, attrname.c_str());
3513 MailWarning(cfg, state, 2,
"Device: %s, Failed SMART usage Attribute: %d %s.", cfg.
name.c_str(), attr.
id, attrname.c_str());
3519 if (!( ( prefail && cfg.
prefail)
3520 || (!prefail && cfg.
usage )))
3528 if (attr.
id != prev.
id) {
3529 PrintOut(LOG_INFO,
"Device: %s, same Attribute has different ID numbers: %d = %d\n",
3530 cfg.
name.c_str(), attr.
id, prev.
id);
3535 bool valchanged =
false;
3542 bool rawchanged =
false;
3550 if (!(valchanged || rawchanged))
3554 std::string currstr, prevstr;
3576 std::string msg =
strprintf(
"Device: %s, SMART %s Attribute: %d %s changed from %s to %s",
3577 cfg.
name.c_str(), (prefail ?
"Prefailure" :
"Usage"), attr.
id,
3579 prevstr.c_str(), currstr.c_str());
3584 PrintOut(LOG_CRIT,
"%s\n", msg.c_str());
3588 PrintOut(LOG_INFO,
"%s\n", msg.c_str());
3595 bool firstpass,
bool allow_selftests)
3600 const char * name = cfg.
name.c_str();
3607 const char * mode = 0;
3608 if (0 <= powermode && powermode < 0xff) {
3613 if (powermode2 > powermode)
3614 PrintOut(LOG_INFO,
"Device: %s, CHECK POWER STATUS spins up disk (0x%02x -> 0x%02x)\n", name, powermode, powermode2);
3615 powermode = powermode2;
3667 mode=
"ACTIVE or IDLE";
3671 PrintOut(LOG_CRIT,
"Device: %s, CHECK POWER STATUS returned %d, not ATA compliant, ignoring -n Directive\n",
3684 PrintOut(LOG_INFO,
"Device: %s, is in %s mode, suspending checks\n", name, mode);
3691 PrintOut(LOG_INFO,
"Device: %s, %s mode ignored due to reached limit of skipped checks (%d check%s skipped)\n",
3698 PrintOut(LOG_INFO,
"Device: %s, is back in %s mode, resuming checks (%d check%s skipped)\n",
3709 PrintOut(LOG_INFO,
"Device: %s, not capable of SMART self-check\n",name);
3710 MailWarning(cfg, state, 5,
"Device: %s, not capable of SMART self-check", name);
3713 else if (status==1){
3714 PrintOut(LOG_CRIT,
"Device: %s, FAILED SMART self-check. BACK UP DATA NOW!\n", name);
3715 MailWarning(cfg, state, 1,
"Device: %s, FAILED SMART self-check. BACK UP DATA NOW!", name);
3729 PrintOut(LOG_CRIT,
"Device: %s, failed to read SMART Attribute Data\n", name);
3730 MailWarning(cfg, state, 6,
"Device: %s, failed to read SMART Attribute Data", name);
3740 :
"Total unreadable (pending) sectors" ));
3745 :
"Total offline uncorrectable sectors"));
3796 int errcnt1 = -1, errcnt2 = -1;
3803 int newc = (errcnt1 >= errcnt2 ? errcnt1 : errcnt2);
3808 MailWarning(cfg, state, 7,
"Device: %s, Read SMART Error Log Failed", name);
3813 PrintOut(LOG_CRIT,
"Device: %s, ATA error count increased from %d to %d\n",
3815 MailWarning(cfg, state, 4,
"Device: %s, ATA error count increased from %d to %d",
3843 const char * name = cfg.
name.c_str();
3845 uint8_t asc = 0, ascq = 0;
3846 uint8_t currenttemp = 0, triptemp = 0;
3849 &asc, &ascq, ¤ttemp, &triptemp)) {
3850 PrintOut(LOG_INFO,
"Device: %s, failed to read SMART values\n",
3852 MailWarning(cfg, state, 6,
"Device: %s, failed to read SMART values", name);
3861 PrintOut(LOG_CRIT,
"Device: %s, SMART Failure: %s\n", name, cp);
3862 MailWarning(cfg, state, 1,
"Device: %s, SMART Failure: %s", name, cp);
3863 }
else if (asc == 4 && ascq == 9) {
3864 PrintOut(LOG_INFO,
"Device: %s, self-test in progress\n", name);
3866 PrintOut(LOG_INFO,
"Device: %s, non-SMART asc,ascq: %d,%d\n",
3867 name, (
int)asc, (
int)ascq);
3869 PrintOut(LOG_INFO,
"Device: %s, SMART health: passed\n", name);
3933 || (firstpass && (
debugmode || curr_op))))
3942 uint8_t op = (curr_op ? curr_op : op0);
3943 const char * t;
char tb[32];
3945 case 0x0: t =
"";
break;
3946 case 0x1: t =
"short";
break;
3947 case 0x2: t =
"extended";
break;
3948 case 0xe: t =
"vendor specific";
break;
3949 default: snprintf(tb,
sizeof(tb),
"unknown (0x%x)", op);
3954 PrintOut(LOG_INFO,
"Device %s, %s self-test in progress, %d%% remaining\n",
3955 name, t, 100 - curr_compl);
3957 else if (!op0 || res0 == 0xf) {
3958 PrintOut(LOG_INFO,
"Device %s, no self-test has ever been run\n", name);
3962 const char * m;
char mb[48];
3964 case 0x0: m =
"completed without error";
break;
3965 case 0x1: m =
"was aborted by a self-test command";
break;
3966 case 0x2: m =
"was aborted by a controller reset";
break;
3967 case 0x3: m =
"was aborted due to a namespace removal";
break;
3968 case 0x4: m =
"was aborted by a format NVM command";
break;
3969 case 0x5: m =
"completed with error (fatal or unknown error)";
break;
3970 case 0x6: m =
"completed with error (unknown failed segment)";
break;
3971 case 0x7: m =
"completed with error (failed segments)";
break;
3972 case 0x8: m =
"was aborted (unknown reason)";
break;
3973 case 0x9: m =
"was aborted due to a sanitize operation";
break;
3974 default: snprintf(mb,
sizeof(mb),
"returned an unknown result (0x%x)", res0);
3980 snprintf(ns,
sizeof(ns),
" of NSID 0x%x", r.
nsid);
3982 PrintOut((0x5 <= res0 && res0 <= 0x7 ? LOG_CRIT : LOG_INFO),
3983 "Device %s, previous %s self-test%s %s\n", name, t, ns, m);
3995 for (
unsigned i = 0; i < 20; i++) {
3999 if (!op || res == 0xf)
4003 || !(r.
valid & 0x01)
4007 if (op == 0x2 && !res )
4010 if (!(0x5 <= res && res <= 0x7))
4027 const char *name = cfg.
name.c_str();
4030 const char *testname; uint8_t stc;
4032 case 'S': testname =
"Short"; stc = 1;
break;
4033 case 'L': testname =
"Extended"; stc = 2;
break;
4035 PrintOut(LOG_INFO,
"Device: %s, not capable of %c Self-Test\n", name, testtype);
4041 PrintOut(LOG_INFO,
"Device: %s, skip scheduled %s Self-Test (NSID 0x%x); %d%% remaining of current Self-Test.\n",
4047 PrintOut(LOG_CRIT,
"Device: %s, execute %s Self-Test failed (NSID 0x%x): %s.\n",
4057 PrintOut(LOG_INFO,
"Device: %s, starting scheduled %s Self-Test (NSID 0x%x).\n",
4058 name, testname,
nsid);
4067 const char * name = cfg.
name.c_str();
4074 PrintOut(LOG_INFO,
"Device: %s, failed to read NVMe SMART/Health Information\n", name);
4075 MailWarning(cfg, state, 6,
"Device: %s, failed to read NVMe SMART/Health Information", name);
4084 static const char *
const wnames[] =
4085 {
"LowSpare",
"Temperature",
"Reliability",
"R/O",
"VolMemBackup"};
4087 for (
unsigned b = 0, cnt = 0;
b < 8 ;
b++) {
4088 if (!(
w & (1 <<
b)))
4093 msg +=
"...";
break;
4095 if (
b >=
sizeof(wnames)/
sizeof(wnames[0])) {
4096 msg +=
"*Unknown*";
break;
4101 PrintOut(LOG_CRIT,
"Device: %s, Critical Warning (0x%02x): %s\n", name,
w, msg.c_str());
4102 MailWarning(cfg, state, 1,
"Device: %s, Critical Warning (0x%02x): %s", name,
w, msg.c_str());
4110 int c = (int)k - 273;
4126 PrintOut(LOG_CRIT,
"Device: %s, Read Self-test Log failed: %s\n",
4128 MailWarning(cfg, state, 8,
"Device: %s, Read Self-test Log failed: %s\n",
4174 bool sts1 =
false, sts2 =
false;
4175 for (
const auto & cfg : configs) {
4176 if (cfg.offlinests_ns)
4178 if (cfg.selfteststs_ns)
4185 if (!
smi()->disable_system_auto_standby(
false)) {
4187 PrintOut(LOG_CRIT,
"System auto standby enable failed: %s\n",
smi()->get_errmsg());
4189 PrintOut(LOG_INFO,
"Disable auto standby not supported, ignoring ',ns' from %s%s%s\n",
4190 (sts1 ?
"-l offlinests,ns" :
""), (sts1 && sts2 ?
" and " :
""), (sts2 ?
"-l selfteststs,ns" :
""));
4191 sts1 = sts2 =
false;
4205 bool running =
false;
4206 for (
unsigned i = 0; i < configs.size() && !running; i++) {
4222 if (!
smi()->disable_system_auto_standby(
false))
4223 PrintOut(LOG_CRIT,
"Self-test(s) completed, system auto standby enable failed: %s\n",
4224 smi()->get_errmsg());
4226 PrintOut(LOG_INFO,
"Self-test(s) completed, system auto standby enabled\n");
4230 else if (!
smi()->disable_system_auto_standby(
true)) {
4232 PrintOut(LOG_INFO,
"Self-test(s) in progress, system auto standby disable rejected: %s\n",
4233 smi()->get_errmsg());
4239 PrintOut(LOG_INFO,
"Self-test(s) in progress, system auto standby disabled\n");
4249 for (
unsigned i = 0; i < configs.size(); i++) {
4254 PrintOut(LOG_INFO,
"Device: %s, skipped (interval=%d)\n", cfg.
name.c_str(),
4295static void ToggleDebugMode()
4298 PrintOut(LOG_INFO,
"Signal USR2 - enabling debug mode\n");
4299 if (!daemon_enable_console(
"smartd [Debug]")) {
4302 PrintOut(LOG_INFO,
"smartd debug mode enabled, PID=%d\n", getpid());
4305 PrintOut(LOG_INFO,
"enable console failed\n");
4308 daemon_disable_console();
4311 PrintOut(LOG_INFO,
"Signal USR2 - debug mode disabled\n");
4320 if (timenow < wakeuptime)
4322 return timenow + ct - (timenow - wakeuptime) % ct;
4329 time_t timenow = time(
nullptr);
4330 unsigned n = configs.size();
4340 for (
unsigned i = 0; i < n; i++) {
4346 if (!wakeuptime || state.
wakeuptime < wakeuptime)
4355 bool no_skip =
false;
4359 if (wakeuptime > timenow + ct) {
4360 PrintOut(LOG_INFO,
"System clock time adjusted to the past. Resetting next wakeup time.\n");
4361 wakeuptime = timenow + ct;
4362 for (
auto & state : states)
4363 state.wakeuptime = 0;
4368 sleep(wakeuptime+addtime-timenow);
4372 if (caughtsigUSR2) {
4378 timenow = time(
nullptr);
4381 if (!addtime && timenow > wakeuptime+60) {
4383 PrintOut(LOG_INFO,
"Sleep time was %d seconds too long, assuming wakeup from standby mode.\n",
4384 (
int)(timenow-wakeuptime));
4386 addtime = timenow-wakeuptime+20;
4388 int nextcheck = ct - addtime % ct;
4389 if (nextcheck <= 20)
4390 addtime += nextcheck;
4396 PrintOut(LOG_INFO,
"Signal USR1 - checking devices now rather than in %d seconds.\n",
4397 wakeuptime-timenow>0?(
int)(wakeuptime-timenow):0);
4399 sigwakeup = no_skip =
true;
4404 for (
auto & state : states)
4405 state.skip = (!no_skip && timenow < state.wakeuptime);
4417 PrintOut(priority,
"never[,N][,q], sleep[,N][,q], standby[,N][,q], idle[,N][,q]");
4420 PrintOut(priority,
"valid_regular_expression");
4423 PrintOut(priority,
"%s",
smi()->get_valid_dev_types_str().c_str());
4426 PrintOut(priority,
"normal, permissive");
4433 PrintOut(priority,
"error, selftest");
4436 PrintOut(priority,
"\"once\", \"always\", \"daily\", \"diminishing\", \"test\", \"exec\"");
4442 PrintOut(priority,
"use, ignore, show, showall");
4448 PrintOut(priority,
"aam,[N|off], apm,[N|off], lookahead,[on|off], dsn,[on|off] "
4449 "security-freeze, standby,[N|off], wcache,[on|off]");
4452 PrintOut(priority,
"i=N, interval=N");
4458static int GetInteger(
const char *arg,
const char *name,
const char *token,
int lineno,
const char *cfgfile,
4459 int min,
int max,
char * suffix = 0)
4463 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s takes integer argument from %d to %d.\n",
4464 cfgfile, lineno, name, token, min, max);
4470 int val = strtol(arg,&endptr,10);
4474 if (!strcmp(endptr, suffix))
4475 endptr += strlen(suffix);
4480 if (!(!*endptr && min <= val && val <= max)) {
4481 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s has argument: %s; needs integer from %d to %d.\n",
4482 cfgfile, lineno, name, token, arg, min, max);
4492static int Get3Integers(
const char *arg,
const char *name,
const char *token,
int lineno,
const char *cfgfile,
4493 unsigned char *val1,
unsigned char *val2,
unsigned char *val3)
4495 unsigned v1 = 0, v2 = 0, v3 = 0;
4496 int n1 = -1, n2 = -1, n3 = -1, len;
4498 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s takes 1-3 integer argument(s) from 0 to 255.\n",
4499 cfgfile, lineno, name, token);
4504 if (!( sscanf(arg,
"%u%n,%u%n,%u%n", &v1, &n1, &v2, &n2, &v3, &n3) >= 1
4505 && (n1 == len || n2 == len || n3 == len) && v1 <= 255 && v2 <= 255 && v3 <= 255)) {
4506 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s has argument: %s; needs 1-3 integer(s) from 0 to 255.\n",
4507 cfgfile, lineno, name, token, arg);
4510 *val1 = (
unsigned char)v1; *val2 = (
unsigned char)v2; *val3 = (
unsigned char)v3;
4518static const char * strtok_dequote(
const char * delimiters)
4520 const char * t = strtok(
nullptr, delimiters);
4521 if (!t || t[0] !=
'"')
4524 static std::string token;
4527 t = strtok(
nullptr, delimiters);
4531 int len = strlen(t);
4532 if (t[len-1] ==
'"') {
4533 token += std::string(t, len-1);
4538 return token.c_str();
4550 const char * name = cfg.
name.c_str();
4552 const char *delim =
" \n\t";
4555 const char *arg = 0;
4562 if (*token!=
'-' || strlen(token)!=2) {
4563 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): unknown Directive: %s\n",
4565 PrintOut(LOG_CRIT,
"Run smartd -D to print a list of valid Directives.\n");
4574 char plus[] =
"+", excl[] =
"!";
4579 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 0, 255, plus)) < 0)
4587 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 0, 255, plus)) < 0)
4595 if (!(arg = strtok(
nullptr, delim))) {
4597 }
else if (!strcmp(arg,
"normal")) {
4602 }
else if (!strcmp(arg,
"permissive")) {
4611 if (!(arg = strtok(
nullptr, delim))) {
4613 }
else if (!strcmp(arg,
"ignore")) {
4615 }
else if (!strcmp(arg,
"removable")) {
4617 }
else if (!strcmp(arg,
"auto")) {
4622 scan_types.push_back(arg);
4627 if (!(arg = strtok(
nullptr, delim)))
4655 if (!(arg = strtok(
nullptr, delim))) {
4657 }
else if (!strcmp(arg,
"selftest")) {
4660 }
else if (!strcmp(arg,
"error")) {
4663 }
else if (!strcmp(arg,
"xerror")) {
4666 }
else if (!strcmp(arg,
"offlinests")) {
4669 }
else if (!strcmp(arg,
"offlinests,ns")) {
4672 }
else if (!strcmp(arg,
"selfteststs")) {
4675 }
else if (!strcmp(arg,
"selfteststs,ns")) {
4678 }
else if (!strncmp(arg,
"scterc,",
sizeof(
"scterc,")-1)) {
4680 unsigned rt = ~0, wt = ~0;
int nc = -1;
4681 sscanf(arg,
"scterc,%u,%u%n", &rt, &wt, &nc);
4682 if (nc == (
int)strlen(arg) && rt <= 999 && wt <= 999) {
4705 if (!(arg = strtok(
nullptr, delim))) {
4707 }
else if (!strcmp(arg,
"on")) {
4709 }
else if (!strcmp(arg,
"off")) {
4717 if (!(arg = strtok(
nullptr, delim)))
4720 char *endptr =
nullptr;
4721 char *next = strchr(
const_cast<char*
>(arg),
',');
4728 if (!strcmp(arg,
"never"))
4730 else if (!strcmp(arg,
"sleep"))
4732 else if (!strcmp(arg,
"standby"))
4734 else if (!strcmp(arg,
"idle"))
4740 if (!badarg && next) {
4746 next = endptr + (*endptr !=
'\0');
4750 if (*next !=
'\0') {
4751 if (!strcmp(
"q", next))
4762 if (!(arg = strtok(
nullptr, delim))) {
4764 }
else if (!strcmp(arg,
"on")) {
4766 }
else if (!strcmp(arg,
"off")) {
4775 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous Test Directive -s %s\n",
4780 if (!(arg = strtok(
nullptr, delim))) {
4787 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): -s argument \"%s\" is INVALID extended regular expression. %s.\n",
4796 "[^]$()*+./:?^[|0-9LSCOncr-]+|"
4797 ":[0-9]{0,2}($|[^0-9])|:[0-9]{4,}|"
4798 ":[0-9]{3}-(000|[0-9]{0,2}($|[^0-9])|[0-9]{4,})"
4801 if (syntax_check.
execute(arg, 1, &range) && 0 <= range.rm_so && range.rm_so < range.rm_eo)
4802 PrintOut(LOG_INFO,
"File %s line %d (drive %s): warning, \"%.*s\" looks odd in "
4803 "extended regular expression \"%s\"\n",
4804 configfile, lineno, name, (
int)(range.rm_eo - range.rm_so), arg + range.rm_so, arg);
4809 if (!(arg = strtok(
nullptr, delim)))
4813 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous Address Directive -m %s\n",
4820 if (!(arg = strtok(
nullptr, delim)))
4822 else if (!strcmp(arg,
"once"))
4824 else if (!strcmp(arg,
"always"))
4826 else if (!strcmp(arg,
"daily"))
4828 else if (!strcmp(arg,
"diminishing"))
4830 else if (!strcmp(arg,
"test"))
4832 else if (!strcmp(arg,
"exec")) {
4836 arg = strtok_dequote(delim);
4837 if (arg && arg[0] ==
'"') {
4838 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive %s 'exec' argument: missing closing quote\n",
4843 arg = strtok(
nullptr, delim);
4846 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive %s 'exec' argument must be followed by executable path.\n",
4852 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous mail Directive -M exec %s\n",
4861 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255)) < 0)
4867 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255)) < 0)
4873 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255, excl)) < 0)
4881 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255, excl)) < 0)
4895 if (!(arg = strtok(
nullptr, delim))) {
4903 if (!(arg = strtok(
nullptr, delim))) {
4905 }
else if (!strcmp(arg,
"use")) {
4907 }
else if (!strcmp(arg,
"ignore")) {
4909 }
else if (!strcmp(arg,
"show")) {
4911 }
else if (!strcmp(arg,
"showall")) {
4920 if (!(arg = strtok(
nullptr, delim))) {
4924 char arg2[16+1];
unsigned uval;
4925 int n1 = -1, n2 = -1, n3 = -1, len = strlen(arg);
4926 if (sscanf(arg,
"%16[^,=]%n%*[,=]%n%u%n", arg2, &n1, &n2, &uval, &n3) >= 1
4927 && (n1 == len || n2 > 0)) {
4928 bool on = (n2 > 0 && !strcmp(arg+n2,
"on"));
4929 bool off = (n2 > 0 && !strcmp(arg+n2,
"off"));
4933 if (!strcmp(arg2,
"aam")) {
4936 else if (uval <= 254)
4941 else if (!strcmp(arg2,
"apm")) {
4944 else if (1 <= uval && uval <= 254)
4949 else if (!strcmp(arg2,
"lookahead")) {
4957 else if (!strcmp(arg,
"security-freeze")) {
4960 else if (!strcmp(arg2,
"standby")) {
4963 else if (uval <= 255)
4968 else if (!strcmp(arg2,
"wcache")) {
4976 else if (!strcmp(arg2,
"dsn")) {
4995 if (!(arg = strtok(
nullptr, delim))) {
4999 int n = 0, nc = -1, len = strlen(arg);
5000 if ( ( sscanf(arg,
"i=%d%n", &n, &nc) == 1
5001 || sscanf(arg,
"interval=%d%n", &n, &nc) == 1)
5002 && nc == len && n >= 10)
5011 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): unknown Directive: %s\n",
5013 PrintOut(LOG_CRIT,
"Run smartd -D to print a list of valid Directives.\n");
5017 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Missing argument to %s Directive\n",
5021 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Invalid argument to %s Directive: %s\n",
5024 if (missingarg || badarg) {
5025 PrintOut(LOG_CRIT,
"Valid arguments to %s Directive are: ", token);
5035#define SCANDIRECTIVE "DEVICESCAN"
5049 const char *delim =
" \n\t";
5052 const char * name = strtok(line, delim);
5053 if (!name || *name ==
'#')
5058 if (!strcmp(
"DEFAULT", name)) {
5066 conf_entries.push_back(default_conf);
5068 dev_config & cfg = (retval ? conf_entries.back() : default_conf);
5075 while (
char * token = strtok(
nullptr, delim)) {
5089 if (retval != -1 && scan_types.size() > 1) {
5090 PrintOut(LOG_CRIT,
"Drive: %s, invalid multiple -d TYPE Directives on line %d of file %s\n",
5106 PrintOut(LOG_INFO,
"Drive: %s, implied '-a' Directive on line %d of file %s\n",
5121 PrintOut(LOG_CRIT,
"Drive: %s, -M Directive(s) on line %d of file %s need -m ADDRESS Directive\n",
5130 PrintOut(LOG_CRIT,
"Drive: %s, -m <nomailer> Directive on line %d of file %s needs -M exec Directive\n",
5155 const int MAXLINELEN = 256;
5157 const int MAXCONTLINE = 1023;
5164 int ret = (errno!=ENOENT ? -3 : -2);
5165 PrintOut(LOG_CRIT,
"%s: Unable to open configuration file %s\n",
5181 if (
ParseConfigLine(conf_entries, default_conf, scan_types, 0, fakeconfig) != -1)
5182 throw std::logic_error(
"Internal error parsing " SCANDIRECTIVE);
5187 setmode(fileno(f), O_TEXT);
5194 int lineno = 1, cont = 0, contlineno = 0;
5195 char line[MAXLINELEN+2];
5196 char fullline[MAXCONTLINE+1];
5199 int len=0,scandevice;
5205 memset(line,0,
sizeof(line));
5208 code=fgets(line, MAXLINELEN+2, f);
5213 scandevice =
ParseConfigLine(conf_entries, default_conf, scan_types, contlineno, fullline);
5231 if (len>MAXLINELEN){
5233 if (line[len-1]==
'\n')
5234 warn=
"(including newline!) ";
5237 PrintOut(LOG_CRIT,
"Error: line %d of file %s %sis more than MAXLINELEN=%d characters.\n",
5238 (
int)contlineno,
configfile,warn,(
int)MAXLINELEN);
5243 if ((comment=strchr(line,
'#'))){
5249 if (cont+len>MAXCONTLINE){
5250 PrintOut(LOG_CRIT,
"Error: continued line %d (actual line %d) of file %s is more than MAXCONTLINE=%d characters.\n",
5251 lineno, (
int)contlineno,
configfile, (
int)MAXCONTLINE);
5256 snprintf(fullline+cont,
sizeof(fullline)-cont,
"%s" ,line);
5260 if ( (lastslash=strrchr(line,
'\\')) && !strtok(lastslash+1,
" \n\t")){
5261 *(fullline+(cont-len)+(lastslash-line))=
' ';
5267 scandevice =
ParseConfigLine(conf_entries, default_conf, scan_types, contlineno, fullline);
5291 PrintOut(LOG_CRIT,
"=======> VALID ARGUMENTS ARE: ");
5293 PrintOut(LOG_CRIT,
"Error constructing argument list for option %c", opt);
5303 if (path.empty() || path[0] ==
'/')
5308 PrintOut(LOG_CRIT,
"=======> INVALID ARGUMENT TO -%c: %s <=======\n\n", option, path.c_str());
5309 PrintOut(LOG_CRIT,
"Error: relative path names are not allowed\n\n");
5320 configfile = SMARTMONTOOLS_SYSCONFDIR
"/smartd.conf";
5321 warning_script = SMARTMONTOOLS_SMARTDSCRIPTDIR
"/smartd_warning.sh";
5324 static std::string configfile_str = exedir +
"/smartd.conf";
5330 static const char shortopts[] =
"c:l:q:dDni:p:r:s:A:B:w:Vh?"
5331#if defined(HAVE_POSIX_API) || defined(_WIN32)
5334#ifdef HAVE_LIBCAP_NG
5339 struct option longopts[] = {
5340 {
"configfile", required_argument, 0,
'c' },
5341 {
"logfacility", required_argument, 0,
'l' },
5342 {
"quit", required_argument, 0,
'q' },
5343 {
"debug", no_argument, 0,
'd' },
5344 {
"showdirectives", no_argument, 0,
'D' },
5345 {
"interval", required_argument, 0,
'i' },
5347 {
"no-fork", no_argument, 0,
'n' },
5349 {
"service", no_argument, 0,
'n' },
5351 {
"pidfile", required_argument, 0,
'p' },
5352 {
"report", required_argument, 0,
'r' },
5353 {
"savestates", required_argument, 0,
's' },
5354 {
"attributelog", required_argument, 0,
'A' },
5355 {
"drivedb", required_argument, 0,
'B' },
5356 {
"warnexec", required_argument, 0,
'w' },
5357 {
"version", no_argument, 0,
'V' },
5358 {
"license", no_argument, 0,
'V' },
5359 {
"copyright", no_argument, 0,
'V' },
5360 {
"help", no_argument, 0,
'h' },
5361 {
"usage", no_argument, 0,
'h' },
5362#if defined(HAVE_POSIX_API) || defined(_WIN32)
5363 {
"warn-as-user", required_argument, 0,
'u' },
5365#ifdef HAVE_LIBCAP_NG
5366 {
"capabilities", optional_argument, 0,
'C' },
5372 bool badarg =
false;
5373 const char * badarg_msg =
nullptr;
5374 bool use_default_db =
true;
5378 while ((optchar = getopt_long(argc, argv, shortopts, longopts,
nullptr)) != -1) {
5387 if (!strcmp(optarg,
"nodev"))
5389 else if (!strcmp(optarg,
"nodev0")) {
5393 else if (!strcmp(optarg,
"nodevstartup"))
5395 else if (!strcmp(optarg,
"nodev0startup")) {
5399 else if (!strcmp(optarg,
"errors"))
5401 else if (!strcmp(optarg,
"errors,nodev0")) {
5405 else if (!strcmp(optarg,
"never"))
5407 else if (!strcmp(optarg,
"onecheck")) {
5411 else if (!strcmp(optarg,
"showtests")) {
5420 if (!strcmp(optarg,
"daemon"))
5422 else if (!strcmp(optarg,
"local0"))
5424 else if (!strcmp(optarg,
"local1"))
5426 else if (!strcmp(optarg,
"local2"))
5428 else if (!strcmp(optarg,
"local3"))
5430 else if (!strcmp(optarg,
"local4"))
5432 else if (!strcmp(optarg,
"local5"))
5434 else if (!strcmp(optarg,
"local6"))
5436 else if (!strcmp(optarg,
"local7"))
5460 lchecktime = strtol(optarg, &tailptr, 10);
5461 if (*tailptr !=
'\0' || lchecktime < 10 || lchecktime > INT_MAX || errno) {
5464 PrintOut(LOG_CRIT,
"======> INVALID INTERVAL: %s <=======\n", optarg);
5465 PrintOut(LOG_CRIT,
"======> INTERVAL MUST BE INTEGER BETWEEN %d AND %d <=======\n", 10, INT_MAX);
5466 PrintOut(LOG_CRIT,
"\nUse smartd -h to get a usage summary\n\n");
5474 int n1 = -1, n2 = -1, len = strlen(optarg);
5475 char s[9+1];
unsigned i = 1;
5476 sscanf(optarg,
"%9[a-z]%n,%u%n",
s, &n1, &i, &n2);
5477 if (!((n1 == len || n2 == len) && 1 <= i && i <= 4)) {
5479 }
else if (!strcmp(
s,
"ioctl")) {
5481 }
else if (!strcmp(
s,
"ataioctl")) {
5483 }
else if (!strcmp(
s,
"scsiioctl")) {
5485 }
else if (!strcmp(
s,
"nvmeioctl")) {
5494 if (strcmp(optarg,
"-"))
5513 const char * path = optarg;
5514 if (*path ==
'+' && path[1])
5517 use_default_db =
false;
5527#ifdef HAVE_POSIX_API
5529 warn_as_user =
false;
5530 if (strcmp(optarg,
"-")) {
5531 warn_uname = warn_gname =
"unknown";
5532 badarg_msg =
parse_ugid(optarg, warn_uid, warn_gid,
5533 warn_uname, warn_gname );
5536 warn_as_user =
true;
5539#elif defined(_WIN32)
5541 if (!strcmp(optarg,
"restricted"))
5542 warn_as_restr_user =
true;
5543 else if (!strcmp(optarg,
"unchanged"))
5544 warn_as_restr_user =
false;
5554#ifdef HAVE_LIBCAP_NG
5558 capabilities_mode = 1;
5559 else if (!strcmp(optarg,
"mail"))
5560 capabilities_mode = 2;
5578 arg = argv[optind <= argc ? optind - 1 : argc - 1];
5580 if (arg[1] ==
'-' && optchar !=
'h') {
5582 if (optopt && strchr(shortopts, optopt)) {
5583 PrintOut(LOG_CRIT,
"=======> ARGUMENT REQUIRED FOR OPTION: %s <=======\n",arg+2);
5586 PrintOut(LOG_CRIT,
"=======> UNRECOGNIZED OPTION: %s <=======\n\n",arg+2);
5588 PrintOut(LOG_CRIT,
"\nUse smartd --help to get a usage summary\n\n");
5593 if (strchr(shortopts, optopt)){
5594 PrintOut(LOG_CRIT,
"=======> ARGUMENT REQUIRED FOR OPTION: %c <=======\n",optopt);
5597 PrintOut(LOG_CRIT,
"=======> UNRECOGNIZED OPTION: %c <=======\n\n",optopt);
5599 PrintOut(LOG_CRIT,
"\nUse smartd -h to get a usage summary\n\n");
5607 if (badarg || badarg_msg) {
5613 PrintOut(LOG_CRIT,
"=======> INVALID ARGUMENT TO -%c: %s <======= \n", optchar, optarg);
5615 PrintOut(LOG_CRIT,
"%s\n", badarg_msg);
5618 PrintOut(LOG_CRIT,
"\nUse smartd -h to get a usage summary\n\n");
5624 if (argc > optind) {
5627 PrintOut(LOG_CRIT,
"=======> UNRECOGNIZED ARGUMENT: %s <=======\n\n", argv[optind]);
5628 PrintOut(LOG_CRIT,
"\nUse smartd -h to get a usage summary\n\n");
5636 PrintOut(LOG_CRIT,
"=======> INVALID CHOICE OF OPTIONS: -d and -p <======= \n\n");
5637 PrintOut(LOG_CRIT,
"Error: pid file %s not written in debug (-d) mode\n\n",
pid_file.c_str());
5652 if (warn_as_restr_user && !popen_as_restr_check()) {
5655 PrintOut(LOG_CRIT,
"Option '--warn-as-user=restricted' is not effective if the current user\n");
5656 PrintOut(LOG_CRIT,
"is the local 'SYSTEM' or 'Administrator' account\n\n");
5690 if (!
smi()->scan_smart_devices(devlist, types)) {
5691 PrintOut(LOG_CRIT,
"DEVICESCAN failed: %s\n",
smi()->get_errmsg());
5696 if (devlist.
size() == 0)
5700 while (scanned_devs.
size() < conf_entries.size())
5704 for (
unsigned i = 0; i < devlist.
size(); i++) {
5710 conf_entries.push_back(base_cfg);
5723 return devlist.
size();
5736 conf_entries.clear();
5747 else if (!conf_entries.empty()) {
5752 conf_entries.pop_back();
5763 if (conf_entries.empty())
5764 PrintOut(LOG_CRIT,
"In the system's table of devices NO devices found to scan\n");
5769 return conf_entries.size();
5782 PrintOut(LOG_INFO,
"Device: %s, unable to autodetect device type\n", cfg.
name.c_str());
5784 PrintOut(LOG_INFO,
"Device: %s, unsupported device type '%s'\n", cfg.
name.c_str(), cfg.
dev_type.c_str());
5798 dev.
replace( dev->autodetect_open() );
5801 if (oldinfo.
dev_type != dev->get_dev_type())
5802 PrintOut(LOG_INFO,
"Device: %s, type changed from '%s' to '%s'\n",
5803 cfg.
name.c_str(), oldinfo.
dev_type.c_str(), dev->get_dev_type());
5806 if (!dev->is_open()) {
5808 PrintOut(LOG_INFO,
"Device: %s, open() failed: %s\n", dev->get_info_name(), dev->get_errmsg());
5813 cfg.
name = dev->get_info().info_name;
5814 PrintOut(LOG_INFO,
"Device: %s, opened\n", cfg.
name.c_str());
5817 const char * typemsg;
5821 status =
ATADeviceScan(cfg, state, dev->to_ata(), prev_cfgs);
5824 else if (dev->is_scsi()){
5829 else if (dev->is_nvme()) {
5834 PrintOut(LOG_INFO,
"Device: %s, neither ATA, SCSI nor NVMe device\n", cfg.
name.c_str());
5841 PrintOut(scanning ? LOG_INFO : LOG_CRIT,
5842 "Unable to register %s device %s at line %d of file %s\n",
5845 PrintOut(LOG_INFO,
"Unable to register %s device %s\n",
5846 typemsg, cfg.
name.c_str());
5867 typedef std::map<std::string, std::string> prev_unique_names_map;
5868 prev_unique_names_map prev_unique_names;
5871 for (
unsigned i = 0; i < conf_entries.size(); i++) {
5877 pout(
"Device: %s%s%s%s, unique name: %s\n", cfg.
name.c_str(),
5879 (!cfg.
dev_type.empty() ?
"]" :
""), unique_name.c_str());
5884 PrintOut(LOG_INFO,
"Device: %s%s%s%s, ignored\n", cfg.
name.c_str(),
5886 (!cfg.
dev_type.empty() ?
"]" :
""));
5887 prev_unique_names[unique_name] = cfg.
name;
5894 bool scanning =
false;
5895 if (i < scanned_devs.
size()) {
5896 dev = scanned_devs.
release(i);
5899 prev_unique_names_map::iterator ui = prev_unique_names.find(unique_name);
5900 if (ui != prev_unique_names.end()) {
5901 bool ne = (ui->second != cfg.
name);
5902 PrintOut(LOG_INFO,
"Device: %s, %s%s, ignored\n", dev->get_info_name(),
5903 (ne ?
"same as " :
"duplicate"), (ne ? ui->second.c_str() :
""));
5921 PrintOut(LOG_CRIT,
"Unable to register device %s (no Directive -d removable). Exiting.\n",
5925 PrintOut(LOG_INFO,
"Device: %s, not available\n", cfg.
name.c_str());
5927 prev_unique_names[unique_name] = cfg.
name;
5933 configs.push_back(cfg);
5934 states.push_back(state);
5938 prev_unique_names[unique_name] = cfg.
name;
5943 unsigned factor = 0;
5944 for (
auto & cfg : configs) {
5947 if (!cfg.test_regex.empty())
5948 cfg.test_offset_factor = factor++;
5987 bool firstpass =
true, write_states_always =
true;
5988 time_t wakeuptime = 0;
6000 "Signal HUP - rereading configuration file %s\n":
6001 "\a\nSignal INT - rereading configuration file %s (" SIGQUIT_KEYNAME " quits)\n\n",
6018 if (!(configs.size() ==
devices.size() && configs.size() == states.size()))
6019 throw std::logic_error(
"Invalid result from RegisterDevices");
6025 PrintOut(LOG_INFO,
"Reusing previous configuration\n");
6037 PrintOut((status ? LOG_CRIT : LOG_INFO),
6038 "Unable to monitor any SMART enabled devices. Exiting.\n");
6043 int numata = 0, numscsi = 0;
6044 for (
unsigned i = 0; i <
devices.size(); i++) {
6051 PrintOut(LOG_INFO,
"Monitoring %d ATA/SATA, %d SCSI/SAS and %d NVMe devices\n",
6052 numata, numscsi, (
int)
devices.size() - numata - numscsi);
6065 write_states_always =
true;
6076 write_states_always =
false;
6084 PrintOut(LOG_INFO,
"Started with '-q onecheck' option. All devices successfully checked once.\n"
6085 "smartd is exiting (exit status 0)\n");
6107 wakeuptime = time(
nullptr);
6113 wakeuptime =
dosleep(wakeuptime, configs, states, write_states_always);
6120 PrintOut(LOG_INFO,
"smartd received signal %d: %s\n",
6125 PrintOut(LOG_CRIT,
"smartd received unexpected signal %d: %s\n",
6144 PrintOut(LOG_CRIT,
"Can't unlink PID file %s (%s).\n",
6145 pid_file.c_str(), strerror(errno));
6148 PrintOut((status ? LOG_CRIT : LOG_INFO),
"smartd is exiting (exit status %d)\n", status);
6158static int smartd_main(
int argc,
char **argv)
6166 catch (
const std::bad_alloc & ) {
6168 PrintOut(LOG_CRIT,
"Smartd: Out of memory\n");
6171 catch (
const std::exception & ex) {
6173 PrintOut(LOG_CRIT,
"Smartd: Exception: %s\n", ex.what());
6179 PrintOut(LOG_CRIT,
"Smartd: Internal Error: %d device object(s) left at exit.\n",
6185 PrintOut(LOG_CRIT,
"Please inform " PACKAGE_BUGREPORT
", including output of smartd -V.\n");
6189 daemon_winsvc_exitcode = status;
6197int main(
int argc,
char **argv){
6199 static const daemon_winsvc_options svc_opts = {
6201 "smartd",
"SmartD Service",
6203 "Controls and monitors storage devices using the Self-Monitoring, "
6204 "Analysis and Reporting Technology System (SMART) built into "
6205 "ATA/SATA and SCSI/SAS hard drives and solid-state drives. "
6206 "www.smartmontools.org"
6211 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)