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