13#define __STDC_FORMAT_MACROS 1
46#include "os_win32/popen.h"
48#pragma warning(disable:4761)
49typedef unsigned short mode_t;
65#include <systemd/sd-daemon.h>
82#include "os_win32/daemon_win32.h"
83#define strsignal daemon_strsignal
84#define sleep daemon_sleep
86#define SIGQUIT SIGBREAK
87#define SIGQUIT_KEYNAME "CONTROL-Break"
89#define SIGQUIT_KEYNAME "CONTROL-\\"
103 daemon_signal(sig, handler);
105#elif defined(HAVE_SIGACTION)
108 sa.sa_handler = SIG_DFL;
109 sigaction(sig, (
struct sigaction *)0, &sa);
110 if (sa.sa_handler == SIG_IGN)
113 memset(&sa, 0,
sizeof(sa));
114 sa.sa_handler = handler;
115 sa.sa_flags = SA_RESTART;
116 sigaction(sig, &sa, (
struct sigaction *)0);
118#elif defined(HAVE_SIGSET)
120 if (sigset(sig, handler) == SIG_IGN)
121 sigset(sig, SIG_IGN);
127 if (signal(sig, handler) == SIG_IGN)
128 signal(sig, SIG_IGN);
138#define EXIT_BADCONF 2
139#define EXIT_STARTUP 3
142#define EXIT_READCONF 6
145#define EXIT_BADCODE 10
147#define EXIT_BADDEV 16
150#define EXIT_SIGNAL 254
166#ifdef SMARTMONTOOLS_SAVESTATES
167 = SMARTMONTOOLS_SAVESTATES
173#ifdef SMARTMONTOOLS_ATTRIBUTELOG
174 = SMARTMONTOOLS_ATTRIBUTELOG
190static bool warn_as_user;
191static uid_t warn_uid;
192static gid_t warn_gid;
193static std::string warn_uname, warn_gname;
196static bool warn_as_restr_user;
223static volatile int caughtsigUSR2=0;
234static void PrintOut(
int priority,
const char *
fmt, ...)
237#ifdef HAVE_LIBSYSTEMD
240static bool notify_enabled =
false;
241static bool notify_ready =
false;
245 if (!getenv(
"NOTIFY_SOCKET"))
247 notify_enabled =
true;
255 PrintOut(LOG_CRIT,
"Option -n (--no-fork) is required if 'Type=notify' is set.\n");
267 const char * notify =
"EXTEND_TIMEOUT_USEC=20000000";
269 pout(
"sd_notify(0, \"%s\")\n", notify);
272 sd_notify(0, notify);
275static void notify_msg(
const char * msg,
bool ready =
false)
280 pout(
"sd_notify(0, \"%sSTATUS=%s\")\n", (ready ?
"READY=1\\n" :
""), msg);
283 sd_notifyf(0,
"%sSTATUS=%s", (ready ?
"READY=1\n" :
""), msg);
291 snprintf(msg,
sizeof(msg),
"Checking %d device%s ...",
292 numdev, (numdev != 1 ?
"s" :
""));
296static void notify_wait(time_t wakeuptime,
int numdev)
300 char ts[16] =
"";
struct tm tmbuf;
303 snprintf(msg,
sizeof(msg),
"Next check of %d device%s will start at %s",
304 numdev, (numdev != 1 ?
"s" :
""), ts);
315 case 0: msg =
"Exiting ...";
break;
316 case EXIT_BADCMD: msg =
"Error in command line (see SYSLOG)";
break;
318 case EXIT_READCONF: msg =
"Error in config file (see SYSLOG)";
break;
319 case EXIT_BADDEV: msg =
"Unable to register a device (see SYSLOG)";
break;
320 case EXIT_NODEV: msg =
"No devices to monitor";
break;
321 default: msg =
"Error (see SYSLOG)";
break;
334 if (getenv(
"NOTIFY_SOCKET")) {
335 PrintOut(LOG_CRIT,
"This version of smartd was build without 'Type=notify' support.\n");
371 bool is_set(
int id,
unsigned char flag)
const
372 {
return (0 <
id &&
id < (
int)
sizeof(
m_flags) && (
m_flags[
id] & flag)); }
376 if (0 <
id &&
id < (
int)
sizeof(
m_flags))
592 | ((uint64_t)ta.
raw[3] << 24)
593 | ((uint64_t)ta.
raw[4] << 32)
594 | ((uint64_t)ta.
raw[5] << 40);
608 memset(ta.
raw, 0,
sizeof(ta.
raw));
613 ta.
raw[0] = (
unsigned char) pa.
raw;
614 ta.
raw[1] = (
unsigned char)(pa.
raw >> 8);
615 ta.
raw[2] = (
unsigned char)(pa.
raw >> 16);
616 ta.
raw[3] = (
unsigned char)(pa.
raw >> 24);
617 ta.
raw[4] = (
unsigned char)(pa.
raw >> 32);
618 ta.
raw[5] = (
unsigned char)(pa.
raw >> 40);
630 "|(self-test-errors)"
631 "|(self-test-last-err-hour)"
632 "|(scheduled-test-next-check)"
633 "|(selective-test-last-start)"
634 "|(selective-test-last-end)"
636 "|(mail\\.([0-9]+)\\."
642 "|(ata-smart-attribute\\.([0-9]+)\\."
650 "|(nvme-err-log-entries)"
652 " *= *([0-9]+)[ \n]*$"
655 const int nmatch = 1+25;
659 if (
match[nmatch-1].rm_so < 0)
662 uint64_t val = strtoull(line +
match[nmatch-1].rm_so, (
char **)0, 10);
665 if (
match[++m].rm_so >= 0)
666 state.
tempmin = (
unsigned char)val;
667 else if (
match[++m].rm_so >= 0)
668 state.
tempmax = (
unsigned char)val;
669 else if (
match[++m].rm_so >= 0)
671 else if (
match[++m].rm_so >= 0)
673 else if (
match[++m].rm_so >= 0)
675 else if (
match[++m].rm_so >= 0)
677 else if (
match[++m].rm_so >= 0)
679 else if (
match[++m].rm_so >= 0)
681 else if (
match[m+=2].rm_so >= 0) {
682 int i = atoi(line+
match[m].rm_so);
687 if (
match[m+=2].rm_so >= 0)
689 else if (
match[++m].rm_so >= 0)
691 else if (
match[++m].rm_so >= 0)
696 else if (
match[m+=5+1].rm_so >= 0) {
697 int i = atoi(line+
match[m].rm_so);
700 if (
match[m+=2].rm_so >= 0)
702 else if (
match[++m].rm_so >= 0)
704 else if (
match[++m].rm_so >= 0)
706 else if (
match[++m].rm_so >= 0)
708 else if (
match[++m].rm_so >= 0)
713 else if (
match[m+7].rm_so >= 0)
726 pout(
"Cannot read state file \"%s\"\n", path);
730 setmode(fileno(f), O_TEXT);
734 int good = 0, bad = 0;
736 while (fgets(line,
sizeof(line), f)) {
737 const char *
s = line + strspn(line,
" \t");
738 if (!*
s || *
s ==
'#')
748 pout(
"%s: format error\n", path);
751 pout(
"%s: %d invalid line(s) ignored\n", path, bad);
762 fprintf(f,
"%s = %" PRIu64
"\n", name, val);
768 fprintf(f,
"%s.%d.%s = %" PRIu64
"\n", name1,
id, name2, val);
775 std::string pathbak = path; pathbak +=
'~';
776 unlink(pathbak.c_str());
777 rename(path, pathbak.c_str());
781 pout(
"Cannot create state file \"%s\"\n", path);
785 fprintf(f,
"# smartd state file\n");
830 pout(
"Cannot create attribute log file \"%s\"\n", path);
835 time_t now = time(
nullptr);
837 fprintf(f,
"%d-%02d-%02d %02d:%02d:%02d;",
838 1900+tms->tm_year, 1+tms->tm_mon, tms->tm_mday,
839 tms->tm_hour, tms->tm_min, tms->tm_sec);
844 fprintf(f,
"\t%d;%d;%" PRIu64
";", pa.id, pa.val, pa.raw);
848 const char * pageNames[3] = {
"read",
"write",
"verify"};
849 for (
int k = 0; k < 3; ++k) {
852 fprintf(f,
"\t%s-corr-by-ecc-fast;%" PRIu64
";"
853 "\t%s-corr-by-ecc-delayed;%" PRIu64
";"
854 "\t%s-corr-by-retry;%" PRIu64
";"
855 "\t%s-total-err-corrected;%" PRIu64
";"
856 "\t%s-corr-algorithm-invocations;%" PRIu64
";"
857 "\t%s-gb-processed;%.3f;"
858 "\t%s-total-unc-errors;%" PRIu64
";",
864 pageNames[k], (ecp->
counter[5] / 1000000000.0),
865 pageNames[k], ecp->
counter[6]);
872 fprintf(f,
"\ttemperature;%d;", state.
temperature);
882 bool write_always =
true)
884 for (
unsigned i = 0; i < states.size(); i++) {
895 PrintOut(LOG_INFO,
"Device: %s, state written to %s\n",
904 for (
unsigned i = 0; i < states.size(); i++) {
928static void USR2handler(
int sig)
959static int capabilities_mode ;
963 if (!capabilities_mode)
965 capng_clear(CAPNG_SELECT_BOTH);
966 capng_updatev(CAPNG_ADD, (capng_type_t)(CAPNG_EFFECTIVE|CAPNG_PERMITTED),
967 CAP_SYS_ADMIN, CAP_MKNOD, CAP_SYS_RAWIO, -1);
968 if (warn_as_user && (warn_uid || warn_gid)) {
970 capng_updatev(CAPNG_ADD, (capng_type_t)(CAPNG_EFFECTIVE|CAPNG_PERMITTED),
971 CAP_SETGID, CAP_SETUID, -1);
973 if (capabilities_mode > 1) {
975 capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET,
976 CAP_SETGID, CAP_SETUID, CAP_CHOWN, CAP_FOWNER, CAP_DAC_OVERRIDE, -1);
978 capng_apply(CAPNG_SELECT_BOTH);
983 if (!capabilities_mode)
985 PrintOut(LOG_INFO,
"If mail notification does not work with '--capabilities%s\n",
986 (capabilities_mode == 1 ?
"', try '--capabilities=mail'"
987 :
"=mail', please inform " PACKAGE_BUGREPORT));
1015 void set(
const char * name,
const char * value);
1022 int size = strlen(name) + 1 + strlen(value) + 1;
1023 char * newbuf =
new char[
size];
1024 snprintf(newbuf,
size,
"%s=%s", name, value);
1027 throw std::runtime_error(
"putenv() failed");
1048 static const char *
const whichfail[] = {
1054 "FailedHealthCheck",
1055 "FailedReadSmartData",
1056 "FailedReadSmartErrorLog",
1057 "FailedReadSmartSelfTestLog",
1059 "CurrentPendingSector",
1060 "OfflineUncorrectableSector",
1066 PrintOut(LOG_CRIT,
"Internal error in MailWarning(): which=%d\n", which);
1074 days = nextdays = -1;
1077 days = nextdays = -1;
break;
1079 days = nextdays = 0;
break;
1081 days = nextdays = 1;
break;
1084 nextdays = 1 << ((unsigned)mail->
logged <= 5 ? mail->
logged : 5);
1086 days = ((unsigned)mail->
logged <= 5 ? nextdays >> 1 : nextdays);
1089 PrintOut(LOG_CRIT,
"Internal error in MailWarning(): cfg.emailfreq=%d\n", (
int)cfg.
emailfreq);
1093 time_t now = time(
nullptr);
1098 if (days > 0 && now < mail->lastsent + days * 24 * 3600)
1122 std::replace(address.begin(), address.end(),
',',
' ');
1128 env[0].
set(
"SMARTD_MAILER", executable);
1129 env[1].
set(
"SMARTD_MESSAGE", message);
1131 snprintf(dates,
sizeof(dates),
"%d", mail->
logged);
1132 env[2].
set(
"SMARTD_PREVCNT", dates);
1134 env[3].
set(
"SMARTD_TFIRST", dates);
1136 env[4].
set(
"SMARTD_TFIRSTEPOCH", dates);
1137 env[5].
set(
"SMARTD_FAILTYPE", whichfail[which]);
1138 env[6].
set(
"SMARTD_ADDRESS", address.c_str());
1139 env[7].
set(
"SMARTD_DEVICESTRING", cfg.
name.c_str());
1142 env[8].
set(
"SMARTD_DEVICETYPE",
1144 env[9].
set(
"SMARTD_DEVICE", cfg.
dev_name.c_str());
1149 snprintf(dates,
sizeof(dates),
"%d", nextdays);
1150 env[11].
set(
"SMARTD_NEXTDAYS", dates);
1152 env[12].
set(
"SMARTD_SUBJECT",
"");
1156 executable =
"<mail>";
1157 const char * newadd = (!address.empty()? address.c_str() :
"<nomailer>");
1158 const char * newwarn = (which?
"Warning via" :
"Test of");
1163 snprintf(command,
sizeof(command),
"\"%s\" 2>&1",
warning_script.c_str());
1165 snprintf(command,
sizeof(command),
"%s 2>&1",
warning_script.c_str());
1169 PrintOut(LOG_INFO,
"%s %s to %s%s ...\n",
1170 (which ?
"Sending warning via" :
"Executing test of"), executable, newadd,
1172#ifdef HAVE_POSIX_API
1175 (
unsigned)warn_uid, warn_uname.c_str(),
1176 (
unsigned)warn_gid, warn_gname.c_str() ).c_str() :
1178 warn_as_restr_user ?
" (restricted user)" :
1188#ifdef HAVE_POSIX_API
1195 pfp = popen_as_restr_user(command,
"r", warn_as_restr_user);
1197 pfp = popen(command,
"r");
1203 PrintOut(LOG_CRIT,
"%s %s to %s: failed (fork or pipe failed, or no memory) %s\n",
1204 newwarn, executable, newadd, errno?strerror(errno):
"");
1215 PrintOut(LOG_CRIT,
"%s %s to %s produced unexpected output (%s%d bytes) to STDOUT/STDERR: \n%s\n",
1216 newwarn, executable, newadd, len!=newlen?
"here truncated to ":
"", newlen,
buffer);
1224 PrintOut(LOG_CRIT,
"%s %s to %s: flushed remaining STDOUT/STDERR\n",
1225 newwarn, executable, newadd);
1227 PrintOut(LOG_CRIT,
"%s %s to %s: more than 1 MB STDOUT/STDERR flushed, breaking pipe\n",
1228 newwarn, executable, newadd);
1235#ifdef HAVE_POSIX_API
1241 status = pclose(pfp);
1245 PrintOut(LOG_CRIT,
"%s %s to %s: pclose(3) failed %s\n", newwarn, executable, newadd,
1246 errno?strerror(errno):
"");
1249 if (WIFEXITED(status)) {
1251 int status8 = WEXITSTATUS(status);
1253 PrintOut(LOG_CRIT,
"%s %s to %s: failed (32-bit/8-bit exit status: %d/%d) perhaps caught signal %d [%s]\n",
1254 newwarn, executable, newadd, status, status8, status8-128, strsignal(status8-128));
1256 PrintOut(LOG_CRIT,
"%s %s to %s: failed (32-bit/8-bit exit status: %d/%d)\n",
1257 newwarn, executable, newadd, status, status8);
1261 PrintOut(LOG_INFO,
"%s %s to %s: successful\n", newwarn, executable, newadd);
1264 if (WIFSIGNALED(status))
1265 PrintOut(LOG_INFO,
"%s %s to %s: exited because of uncaught signal %d [%s]\n",
1266 newwarn, executable, newadd, WTERMSIG(status), strsignal(WTERMSIG(status)));
1270 if (WIFSTOPPED(status))
1271 PrintOut(LOG_CRIT,
"%s %s to %s: process STOPPED because it caught signal %d [%s]\n",
1272 newwarn, executable, newadd, WSTOPSIG(status), strsignal(WSTOPSIG(status)));
1301 PrintOut(LOG_INFO,
"Device: %s, %s, warning condition reset after %d email%s\n", cfg.
name.c_str(),
1313static
void vsyslog_lines(
int priority, const
char *
fmt, va_list
ap)
1318 for (
char * p = buf, * q; p && *p; p = q) {
1319 if ((q = strchr(p,
'\n')))
1322 syslog(priority,
"%s\n", p);
1328#define vsyslog_lines vsyslog
1352 vfprintf(f,
fmt,
ap);
1357 openlog(
"smartd", LOG_PID,
facility);
1358 vsyslog_lines(LOG_INFO,
fmt,
ap);
1379 vfprintf(f,
fmt,
ap);
1383 openlog(
"smartd", LOG_PID,
facility);
1384 vsyslog_lines(priority,
fmt,
ap);
1394 pout(
"Warning! %s error: invalid SMART checksum.\n",
string);
1403 int waited, max_wait = 10;
1404 struct stat stat_buf;
1409 for(waited = 0; waited < max_wait; ++waited) {
1410 if (!stat(
pid_file.c_str(), &stat_buf)) {
1434 if ((pid=fork()) < 0) {
1436 PrintOut(LOG_CRIT,
"smartd unable to fork daemon process!\n");
1452 if ((pid=fork()) < 0) {
1454 PrintOut(LOG_CRIT,
"smartd unable to fork daemon process!\n");
1465 for (
int i = sysconf(_SC_OPEN_MAX); --i >= 0; )
1469 int fd = open(
"/dev/null", O_RDWR);
1470 if (!(fd == 0 && dup(fd) == 1 && dup(fd) == 2 && !chdir(
"/"))) {
1471 PrintOut(LOG_CRIT,
"smartd unable to redirect to /dev/null or to chdir to root!\n");
1477 PrintOut(LOG_INFO,
"smartd has fork()ed into background mode. New PID=%d.\n", (
int)getpid());
1484 if (daemon_detach(
"smartd")) {
1485 PrintOut(LOG_CRIT,
"smartd unable to detach from console!\n");
1500 pid_t pid = getpid();
1503 old_umask = umask(0077);
1506 old_umask = umask(0033);
1511 if (!(f && fprintf(f,
"%d\n", (
int)pid) > 0 && f.
close())) {
1512 PrintOut(LOG_CRIT,
"unable to write PID file %s - exiting.\n",
pid_file.c_str());
1515 PrintOut(LOG_INFO,
"file %s written containing PID %d\n",
pid_file.c_str(), (
int)pid);
1530 "Configuration file (%s) Directives (after device name):\n"
1531 " -d TYPE Set the device type: auto, ignore, removable,\n"
1533 " -T TYPE Set the tolerance to one of: normal, permissive\n"
1534 " -o VAL Enable/disable automatic offline tests (on/off)\n"
1535 " -S VAL Enable/disable attribute autosave (on/off)\n"
1536 " -n MODE No check if: never, sleep[,N][,q], standby[,N][,q], idle[,N][,q]\n"
1537 " -H Monitor SMART Health Status, report if failed\n"
1538 " -s REG Do Self-Test at time(s) given by regular expression REG\n"
1539 " -l TYPE Monitor SMART log or self-test status:\n"
1540 " error, selftest, xerror, offlinests[,ns], selfteststs[,ns]\n"
1541 " -l scterc,R,W Set SCT Error Recovery Control\n"
1542 " -e Change device setting: aam,[N|off], apm,[N|off], dsn,[on|off],\n"
1543 " lookahead,[on|off], security-freeze, standby,[N|off], wcache,[on|off]\n"
1544 " -f Monitor 'Usage' Attributes, report failures\n"
1545 " -m ADD Send email warning to address ADD\n"
1546 " -M TYPE Modify email warning behavior (see man page)\n"
1547 " -p Report changes in 'Prefailure' Attributes\n"
1548 " -u Report changes in 'Usage' Attributes\n"
1549 " -t Equivalent to -p and -u Directives\n"
1550 " -r ID Also report Raw values of Attribute ID with -p, -u or -t\n"
1551 " -R ID Track changes in Attribute ID Raw value with -p, -u or -t\n"
1552 " -i ID Ignore Attribute ID for -f Directive\n"
1553 " -I ID Ignore Attribute ID for -p, -u or -t Directive\n"
1554 " -C ID[+] Monitor [increases of] Current Pending Sectors in Attribute ID\n"
1555 " -U ID[+] Monitor [increases of] Offline Uncorrectable Sectors in Attribute ID\n"
1556 " -W D,I,C Monitor Temperature D)ifference, I)nformal limit, C)ritical limit\n"
1557 " -v N,ST Modifies labeling of Attribute N (see man page) \n"
1558 " -P TYPE Drive-specific presets: use, ignore, show, showall\n"
1559 " -a Default: -H -f -t -l error -l selftest -l selfteststs -C 197 -U 198\n"
1560 " -F TYPE Use firmware bug workaround:\n"
1562 " -c i=N Set interval between disk checks to N seconds\n"
1563 " # Comment: text after a hash sign is ignored\n"
1564 " \\ Line continuation character\n"
1565 "Attribute ID is a decimal integer 1 <= ID <= 255\n"
1566 "Use ID = 0 to turn off -C and/or -U Directives\n"
1567 "Example: /dev/sda -a\n",
1569 smi()->get_valid_dev_types_str().c_str(),
1580 return "<PATH_PREFIX>, -";
1582 return "[+]<FILE_NAME>";
1584 return "<FILE_NAME>, -";
1586 return "daemon, local0, local1, local2, local3, local4, local5, local6, local7";
1588 return "nodev[0], errors[,nodev0], nodev[0]startup, never, onecheck, showtests";
1590 return "ioctl[,N], ataioctl[,N], scsiioctl[,N], nvmeioctl[,N]";
1593 return "<FILE_NAME>";
1595 return "<INTEGER_SECONDS>";
1596#ifdef HAVE_POSIX_API
1598 return "<USER>[:<GROUP>], -";
1599#elif defined(_WIN32)
1601 return "restricted, unchanged";
1603#ifdef HAVE_LIBCAP_NG
1605 return "mail, <no_argument>";
1615 PrintOut(LOG_INFO,
"Usage: smartd [options]\n\n");
1616#ifdef SMARTMONTOOLS_ATTRIBUTELOG
1617 PrintOut(LOG_INFO,
" -A PREFIX|-, --attributelog=PREFIX|-\n");
1619 PrintOut(LOG_INFO,
" -A PREFIX, --attributelog=PREFIX\n");
1621 PrintOut(LOG_INFO,
" Log attribute information to {PREFIX}MODEL-SERIAL.TYPE.csv\n");
1622#ifdef SMARTMONTOOLS_ATTRIBUTELOG
1623 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_ATTRIBUTELOG
"MODEL-SERIAL.TYPE.csv]\n");
1626 PrintOut(LOG_INFO,
" -B [+]FILE, --drivedb=[+]FILE\n");
1627 PrintOut(LOG_INFO,
" Read and replace [add] drive database from FILE\n");
1629#ifdef SMARTMONTOOLS_DRIVEDBDIR
1631 PrintOut(LOG_INFO,
" and then %s", get_drivedb_path_default());
1634 PrintOut(LOG_INFO,
" -c NAME|-, --configfile=NAME|-\n");
1635 PrintOut(LOG_INFO,
" Read configuration file NAME or stdin\n");
1637#ifdef HAVE_LIBCAP_NG
1638 PrintOut(LOG_INFO,
" -C, --capabilities[=mail]\n");
1639 PrintOut(LOG_INFO,
" Drop unneeded Linux process capabilities.\n"
1640 " Warning: Mail notification may not work when used.\n\n");
1642 PrintOut(LOG_INFO,
" -d, --debug\n");
1643 PrintOut(LOG_INFO,
" Start smartd in debug mode\n\n");
1644 PrintOut(LOG_INFO,
" -D, --showdirectives\n");
1645 PrintOut(LOG_INFO,
" Print the configuration file Directives and exit\n\n");
1646 PrintOut(LOG_INFO,
" -h, --help, --usage\n");
1647 PrintOut(LOG_INFO,
" Display this help and exit\n\n");
1648 PrintOut(LOG_INFO,
" -i N, --interval=N\n");
1649 PrintOut(LOG_INFO,
" Set interval between disk checks to N seconds, where N >= 10\n\n");
1650 PrintOut(LOG_INFO,
" -l local[0-7], --logfacility=local[0-7]\n");
1652 PrintOut(LOG_INFO,
" Use syslog facility local0 - local7 or daemon [default]\n\n");
1654 PrintOut(LOG_INFO,
" Log to \"./smartd.log\", stdout, stderr [default is event log]\n\n");
1657 PrintOut(LOG_INFO,
" -n, --no-fork\n");
1658 PrintOut(LOG_INFO,
" Do not fork into background\n");
1659#ifdef HAVE_LIBSYSTEMD
1660 PrintOut(LOG_INFO,
" (systemd 'Type=notify' is assumed if $NOTIFY_SOCKET is set)\n");
1664 PrintOut(LOG_INFO,
" -p NAME, --pidfile=NAME\n");
1665 PrintOut(LOG_INFO,
" Write PID file NAME\n\n");
1666 PrintOut(LOG_INFO,
" -q WHEN, --quit=WHEN\n");
1668 PrintOut(LOG_INFO,
" -r, --report=TYPE\n");
1670#ifdef SMARTMONTOOLS_SAVESTATES
1671 PrintOut(LOG_INFO,
" -s PREFIX|-, --savestates=PREFIX|-\n");
1673 PrintOut(LOG_INFO,
" -s PREFIX, --savestates=PREFIX\n");
1675 PrintOut(LOG_INFO,
" Save disk states to {PREFIX}MODEL-SERIAL.TYPE.state\n");
1676#ifdef SMARTMONTOOLS_SAVESTATES
1677 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_SAVESTATES
"MODEL-SERIAL.TYPE.state]\n");
1680 PrintOut(LOG_INFO,
" -w NAME, --warnexec=NAME\n");
1681 PrintOut(LOG_INFO,
" Run executable NAME on warnings\n");
1683 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_SMARTDSCRIPTDIR
"/smartd_warning.sh]\n\n");
1687#ifdef HAVE_POSIX_API
1688 PrintOut(LOG_INFO,
" -u USER[:GROUP], --warn-as-user=USER[:GROUP]\n");
1689 PrintOut(LOG_INFO,
" Run warning script as non-privileged USER\n\n");
1690#elif defined(_WIN32)
1691 PrintOut(LOG_INFO,
" -u MODE, --warn-as-user=MODE\n");
1696 PrintOut(LOG_INFO,
" Running as windows service (see man page), install with:\n");
1697 PrintOut(LOG_INFO,
" smartd install [options]\n");
1698 PrintOut(LOG_INFO,
" Remove service with:\n");
1699 PrintOut(LOG_INFO,
" smartd remove\n\n");
1701 PrintOut(LOG_INFO,
" -V, --version, --license, --copyright\n");
1702 PrintOut(LOG_INFO,
" Print License, Copyright, and version information\n");
1707 if (!device->
close()){
1718 bool changed =
false;
1719 for (
unsigned i = 0; i <
s.size(); i++) {
1723 if ((
' ' <= c && c <=
'~') && !(i == 0 && c ==
'~'))
1734 return !( (
'0' <= c && c <=
'9')
1735 || (
'A' <= c && c <=
'Z')
1736 || (
'a' <= c && c <=
'z'));
1747 PrintOut(LOG_INFO,
"Device: %s, Read Summary SMART Error Log failed\n",name);
1755 PrintOut(LOG_INFO,
"Device: %s, Read Extended Comprehensive SMART Error Log failed\n",name);
1771 PrintOut(LOG_INFO,
"Device: %s, Read SMART Self Test Log Failed\n",name);
1780 int errcnt = 0, hours = 0;
1781 for (
int i = 20; i >= 0; i--) {
1787 int status =
entry.selfteststatus >> 4;
1788 if (status == 0x0 && (
entry.selftestnumber & 0x7f) == 0x02)
1792 if (0x3 <= status && status <= 0x8) {
1797 hours =
entry.timestamp;
1801 return ((hours << 8) | errcnt);
1804#define SELFTEST_ERRORCOUNT(x) (x & 0xff)
1805#define SELFTEST_ERRORHOURS(x) ((x >> 8) & 0xffff)
1810 return ((status & 0x7f) == 0x03);
1816 return ((status >> 4) == 0xf);
1823 switch (status & 0x7f) {
1824 case 0x00: msg =
"was never started";
break;
1825 case 0x02: msg =
"was completed without error";
break;
1826 case 0x03: msg =
"is in progress";
break;
1827 case 0x04: msg =
"was suspended by an interrupting command from host";
break;
1828 case 0x05: msg =
"was aborted by an interrupting command from host";
break;
1829 case 0x06: msg =
"was aborted by the device with a fatal error";
break;
1830 default: msg =
nullptr;
1834 PrintOut(((status & 0x7f) == 0x06 ? LOG_CRIT : LOG_INFO),
1835 "Device: %s, offline data collection %s%s\n", name, msg,
1836 ((status & 0x80) ?
" (auto:on)" :
""));
1838 PrintOut(LOG_INFO,
"Device: %s, unknown offline data collection status 0x%02x\n",
1846 switch (status >> 4) {
1847 case 0x0: msg =
"completed without error";
break;
1848 case 0x1: msg =
"was aborted by the host";
break;
1849 case 0x2: msg =
"was interrupted by the host with a reset";
break;
1850 case 0x3: msg =
"could not complete due to a fatal or unknown error";
break;
1851 case 0x4: msg =
"completed with error (unknown test element)";
break;
1852 case 0x5: msg =
"completed with error (electrical test element)";
break;
1853 case 0x6: msg =
"completed with error (servo/seek test element)";
break;
1854 case 0x7: msg =
"completed with error (read test element)";
break;
1855 case 0x8: msg =
"completed with error (handling damage?)";
break;
1856 default: msg =
nullptr;
1860 PrintOut(((status >> 4) >= 0x4 ? LOG_CRIT : LOG_INFO),
1861 "Device: %s, previous self-test %s\n", name, msg);
1862 else if ((status >> 4) == 0xf)
1863 PrintOut(LOG_INFO,
"Device: %s, self-test in progress, %u0%% remaining\n",
1864 name, status & 0x0f);
1866 PrintOut(LOG_INFO,
"Device: %s, unknown self-test status 0x%02x\n",
1872 unsigned char id,
const char * msg)
1877 PrintOut(LOG_INFO,
"Device: %s, can't monitor %s count - no Attribute %d\n",
1878 cfg.
name.c_str(), msg,
id);
1886 PrintOut(LOG_INFO,
"Device: %s, ignoring %s count - bogus Attribute %d value %" PRIu64
" (0x%" PRIx64
")\n",
1887 cfg.
name.c_str(), msg,
id, rawval, rawval);
1913 int set_option = 0,
bool has_value =
false)
1920 else if (set_option < 0)
1924 else if (set_option > 0)
1934 for (
const auto & prev_cfg : prev_cfgs) {
1935 if (!prev_cfg.id_is_unique)
1940 PrintOut(LOG_INFO,
"Device: %s, same identity as %s, ignored\n",
1941 cfg.
dev_name.c_str(), prev_cfg.dev_name.c_str());
1957 const char *name = cfg.
name.c_str();
1966 PrintOut(LOG_INFO,
"Device: %s, not ATA, no IDENTIFY DEVICE Structure\n",name);
1968 PrintOut(LOG_INFO,
"Device: %s, packet devices [this device %s] not SMART capable\n",
1975 char model[40+1], serial[20+1], firmware[8+1];
1985 char wwn[64]; wwn[0] = 0;
1986 unsigned oui = 0; uint64_t unique_id = 0;
1989 snprintf(wwn,
sizeof(wwn),
"WWN:%x-%06x-%09" PRIx64
", ", naa, oui, unique_id);
2010 PrintOut(LOG_INFO,
"Device: %s, smartd database not searched (Directive: -P ignore).\n", name);
2013 std::string dbversion;
2017 PrintOut(LOG_INFO,
"Device: %s, not found in smartd database%s%s.\n", name,
2018 (!dbversion.empty() ?
" " :
""), (!dbversion.empty() ? dbversion.c_str() :
""));
2020 PrintOut(LOG_INFO,
"Device: %s, found in smartd database%s%s%s%s\n",
2021 name, (!dbversion.empty() ?
" " :
""), (!dbversion.empty() ? dbversion.c_str() :
""),
2030 bool locked = ((word128 & 0x0007) == 0x0007);
2032 PrintOut(LOG_INFO,
"Device: %s, ATA Security is **LOCKED**\n", name);
2044 PrintOut(LOG_INFO,
"Device %s: presets are:\n", name);
2056 PrintOut(LOG_INFO,
"Device: %s, lacks SMART capability\n",name);
2059 PrintOut(LOG_INFO,
"Device: %s, ATA IDENTIFY DEVICE words 82-83 don't specify if SMART capable.\n",name);
2063 PrintOut(LOG_INFO,
"Device: %s, proceeding since '-T permissive' Directive given.\n",name);
2066 PrintOut(LOG_INFO,
"Device: %s, to proceed anyway, use '-T permissive' Directive.\n",name);
2074 PrintOut(LOG_INFO,
"Device: %s, could not enable SMART capability\n",name);
2078 PrintOut(LOG_INFO,
"Device: %s, to proceed anyway, use '-T permissive' Directive.\n", name);
2082 PrintOut(LOG_INFO,
"Device: %s, proceeding since '-T permissive' Directive given.\n", name);
2085 PrintOut(LOG_INFO,
"Device: %s, proceeding since SMART is already enabled\n", name);
2092 PrintOut(LOG_INFO,
"Device: %s, could not disable SMART Attribute Autosave.\n",name);
2094 PrintOut(LOG_INFO,
"Device: %s, disabled SMART Attribute Autosave.\n",name);
2100 PrintOut(LOG_INFO,
"Device: %s, could not enable SMART Attribute Autosave.\n",name);
2102 PrintOut(LOG_INFO,
"Device: %s, enabled SMART Attribute Autosave.\n",name);
2107 PrintOut(LOG_INFO,
"Device: %s, not capable of SMART Health Status check\n",name);
2118 bool smart_val_ok =
false;
2127 PrintOut(LOG_INFO,
"Device: %s, Read SMART Values failed\n", name);
2133 smart_val_ok =
true;
2135 PrintOut(LOG_INFO,
"Device: %s, Read SMART Thresholds failed%s\n",
2136 name, (cfg.
usagefailed ?
", ignoring -f Directive" :
""));
2147 "Current_Pending_Sector"))
2152 "Offline_Uncorrectable"))
2157 PrintOut(LOG_INFO,
"Device: %s, can't monitor Temperature, ignoring -W %d,%d,%d\n",
2163 for (
int id = 1;
id <= 255;
id++) {
2171 PrintOut(LOG_INFO,
"Device: %s, no Attribute %d, ignoring -%c %d%s\n", name,
id, opt,
id, excl);
2174 if (!((prefail && cfg.
prefail) || (!prefail && cfg.
usage)))
2175 PrintOut(LOG_INFO,
"Device: %s, not monitoring %s Attributes, ignoring -%c %d%s\n", name,
2176 (prefail ?
"Prefailure" :
"Usage"), opt,
id, excl);
2187 PrintOut(LOG_INFO,
"Device: %s, could not %s SMART Automatic Offline Testing.\n",name, what);
2191 PrintOut(LOG_INFO,
"Device: %s, SMART Automatic Offline Testing unsupported...\n",name);
2194 PrintOut(LOG_INFO,
"Device: %s, %s SMART Automatic Offline Testing failed.\n", name, what);
2196 PrintOut(LOG_INFO,
"Device: %s, %sd SMART Automatic Offline Testing.\n", name, what);
2202 bool smart_logdir_ok =
false, gp_logdir_ok =
false;
2208 smart_logdir_ok =
true;
2213 gp_logdir_ok =
true;
2223 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test Log, ignoring -l selftest (override with -T permissive)\n", name);
2227 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test Log, ignoring -l selftest\n", name);
2243 PrintOut(LOG_INFO,
"Device: %s, no SMART Error Log, ignoring -l error (override with -T permissive)\n", name);
2247 PrintOut(LOG_INFO,
"Device: %s, no SMART Error Log, ignoring -l error\n", name);
2258 PrintOut(LOG_INFO,
"Device: %s, no Extended Comprehensive SMART Error Log, ignoring -l xerror (override with -T permissive)\n",
2263 PrintOut(LOG_INFO,
"Device: %s, no Extended Comprehensive SMART Error Log, ignoring -l xerror\n", name);
2267 PrintOut(LOG_INFO,
"Device: %s, SMART Error Logs report different error counts: %d != %d\n",
2281 PrintOut(LOG_INFO,
"Device: %s, no SMART Offline Data Collection capability, ignoring -l offlinests (override with -T permissive)\n", name);
2283 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test capability, ignoring -l selfteststs (override with -T permissive)\n", name);
2292 if (-1 == powermode) {
2293 PrintOut(LOG_CRIT,
"Device: %s, no ATA CHECK POWER STATUS support, ignoring -n Directive\n", name);
2296 else if (powermode!=0x00 && powermode!=0x01
2297 && powermode!=0x40 && powermode!=0x41
2298 && powermode!=0x80 && powermode!=0x81 && powermode!=0x82 && powermode!=0x83
2299 && powermode!=0xff) {
2300 PrintOut(LOG_CRIT,
"Device: %s, CHECK POWER STATUS returned %d, not ATA compliant, ignoring -n Directive\n",
2342 PrintOut(LOG_INFO,
"Device: %s, ATA settings applied: %s\n", name, msg.c_str());
2347 PrintOut(LOG_INFO,
"Device: %s, no SCT Error Recovery Control support, ignoring -l scterc\n",
2350 PrintOut(LOG_INFO,
"Device: %s, no SCT support if ATA Security is LOCKED, ignoring -l scterc\n",
2354 PrintOut(LOG_INFO,
"Device: %s, set of SCT Error Recovery Control failed\n", name);
2356 PrintOut(LOG_INFO,
"Device: %s, SCT Error Recovery Control set to: Read: %u, Write: %u\n",
2371 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n",name);
2384 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", name, cfg.
state_file.c_str());
2403 int err, req_len, avail_len, version, len;
2404 const char *device = cfg.
name.c_str();
2408 uint8_t vpdBuf[252];
2409 char lu_id[64], serial[256], vendor[40], model[40];
2412 memset(inqBuf, 0, 96);
2419 PrintOut(LOG_INFO,
"Device: %s, Both 36 and 64 byte INQUIRY failed; "
2420 "skip device [err=%d, %d]\n", device, err, err64);
2424 version = (inqBuf[2] & 0x7f);
2426 avail_len = inqBuf[4] + 5;
2427 len = (avail_len < req_len) ? avail_len : req_len;
2429 PrintOut(LOG_INFO,
"Device: %s, INQUIRY response less than 36 bytes; "
2430 "skip device\n", device);
2434 int pdt = inqBuf[0] & 0x1f;
2445 PrintOut(LOG_INFO,
"Device: %s, not a disk like device [PDT=0x%x], "
2446 "skip\n", device, pdt);
2457 if (version >= 0x3) {
2460 vpdBuf,
sizeof(vpdBuf))) {
2467 vpdBuf,
sizeof(vpdBuf))) {
2469 vpdBuf[4 + len] =
'\0';
2484 (
char *)&inqBuf[8], (
char *)&inqBuf[16], (
char *)&inqBuf[32],
2485 (lu_id[0] ?
", lu id: " :
""), (lu_id[0] ? lu_id :
""),
2486 (serial[0] ?
", S/N: " :
""), (serial[0] ? serial :
""),
2487 (si_str[0] ?
", " :
""), (si_str[0] ? si_str :
""));
2507 PrintOut(LOG_INFO,
"Device: %s, NOT READY (e.g. spun down); skip device\n", device);
2509 PrintOut(LOG_INFO,
"Device: %s, NO MEDIUM present; skip device\n", device);
2511 PrintOut(LOG_INFO,
"Device: %s, BECOMING (but not yet) READY; skip device\n", device);
2513 PrintOut(LOG_CRIT,
"Device: %s, failed Test Unit Ready [err=%d]\n", device, err);
2530 "Device: %s, Bad IEC (SMART) mode page, err=%d, skip device\n",
2539 PrintOut(LOG_INFO,
"Device: %s, IE (SMART) not enabled, skip device\n"
2540 "Try 'smartctl -s on %s' to turn on SMART features\n",
2582 uint8_t currenttemp = 0;
2583 uint8_t triptemp = 0;
2586 &asc, &ascq, ¤ttemp, &triptemp)) {
2587 PrintOut(LOG_INFO,
"Device: %s, unexpectedly failed to read SMART values\n", device);
2592 PrintOut(LOG_INFO,
"Device: %s, can't monitor Temperature, ignoring -W %d,%d,%d\n",
2603 PrintOut(LOG_INFO,
"Device: %s, does not support SMART Self-Test Log.\n", device);
2618 PrintOut(LOG_INFO,
"Device: %s, could not disable autosave (set GLTSD bit).\n",device);
2620 PrintOut(LOG_INFO,
"Device: %s, disabled autosave (set GLTSD bit).\n",device);
2626 PrintOut(LOG_INFO,
"Device: %s, could not enable autosave (clear GLTSD bit).\n",device);
2628 PrintOut(LOG_INFO,
"Device: %s, enabled autosave (cleared GLTSD bit).\n",device);
2632 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n", device);
2648 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", device, cfg.
state_file.c_str());
2665 for (
int i = 8; i < 16; i++) {
2667 return ~(uint64_t)0;
2669 uint64_t lo = val[7];
2670 for (
int i = 7-1; i >= 0; i--) {
2671 lo <<= 8; lo += val[i];
2689 uint64_t newcnt = 0)
2693 unsigned want_entries = 64;
2700 if (!read_entries) {
2701 PrintOut(LOG_INFO,
"Device: %s, Read %u entries from Error Information Log failed\n",
2702 cfg.
name.c_str(), want_entries);
2711 int err = 0, ign = 0;
2712 for (
unsigned i = 0; i < read_entries; i++) {
2732 PrintOut(LOG_INFO,
"Device: %s, NVMe error [%u], count %" PRIu64
", status 0x%04x: %s\n",
2737 std::string msg =
strprintf(
"Device: %s, NVMe error count increased from %" PRIu64
" to %" PRIu64
2738 " (%d new, %d ignored, %" PRIu64
" unknown)",
2739 cfg.
name.c_str(), oldcnt, newcnt, err, ign,
2740 (mincnt > oldcnt + 1 ? mincnt - oldcnt - 1 : 0));
2743 PrintOut(LOG_INFO,
"%s\n", msg.c_str());
2746 PrintOut(LOG_CRIT,
"%s\n", msg.c_str());
2758 const char *name = cfg.
name.c_str();
2765 PrintOut(LOG_INFO,
"Device: %s, NVMe Identify Controller failed\n", name);
2771 char model[40+1], serial[20+1], firmware[8+1];
2777 char nsstr[32] =
"", capstr[32] =
"";
2779 if (
nsid != 0xffffffff)
2780 snprintf(nsstr,
sizeof(nsstr),
", NSID:%u",
nsid);
2785 nsstr, (capstr[0] ?
", " :
""), capstr);
2801 PrintOut(LOG_INFO,
"Device: %s, failed to read NVMe SMART/Health Information\n", name);
2809 PrintOut(LOG_INFO,
"Device: %s, no Temperature sensors, ignoring -W %d,%d,%d\n",
2819 PrintOut(LOG_INFO,
"Device: %s, Error Information unavailable, ignoring -l [x]error\n", name);
2834 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n", name);
2846 if (
nsid != 0xffffffff)
2847 snprintf(nsstr,
sizeof(nsstr),
"-n%u",
nsid);
2851 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", name, cfg.
state_file.c_str());
2863 const char * name = cfg.
name.c_str();
2867 MailWarning(cfg, state, 0,
"TEST EMAIL from smartd for device: %s", name);
2882 PrintOut(LOG_INFO,
"Device: %s, is in %s mode, suspending checks\n", name,
"STANDBY (OS)");
2893 if (!device->
open()) {
2896 PrintOut(LOG_INFO,
"Device: %s, open() of %s device failed: %s\n", name, type, device->
get_errmsg());
2897 MailWarning(cfg, state, 9,
"Device: %s, unable to open %s device", name, type);
2900 PrintOut(LOG_INFO,
"Device: %s, removed %s device: %s\n", name, type, device->
get_errmsg());
2904 PrintOut(LOG_INFO,
"Device: %s, %s device still removed: %s\n", name, type, device->
get_errmsg());
2909 PrintOut(LOG_INFO,
"Device: %s, opened %s device\n", name, type);
2914 PrintOut(LOG_INFO,
"Device: %s, reconnected %s device\n", name, type);
2925 const char * name = cfg.
name.c_str();
2929 MailWarning(cfg, state, 8,
"Device: %s, Read SMART Self-Test Log Failed", name);
2943 PrintOut(LOG_CRIT,
"Device: %s, Self-Test Log error count increased from %d to %d\n",
2945 MailWarning(cfg, state, 3,
"Device: %s, Self-Test Log error count increased from %d to %d",
2949 else if (newc > 0 && oldh != newh) {
2957 PrintOut(LOG_CRIT,
"Device: %s, new Self-Test Log error at hour timestamp %d\n",
2959 MailWarning(cfg, state, 3,
"Device: %s, new Self-Test Log error at hour timestamp %d",
2967 PrintOut(LOG_INFO,
"Device: %s, Self-Test Log error count decreased from %d to %d\n",
3004 time_t now = (!usetime ? time(
nullptr) : usetime);
3018 unsigned offsets[max_offsets] = {0, }, limits[max_offsets] = {0, };
3019 unsigned num_offsets = 1;
3021 const char * q = strchr(p,
':');
3025 unsigned offset = 0, limit = 0;
int n1 = -1, n2 = -1, n3 = -1;
3026 sscanf(p,
"%u%n-%n%u%n", &offset, &n1, &n2, &limit, &n3);
3027 if (!(n1 == 3 && (n2 < 0 || (n3 == 3+1+3 && limit > 0))))
3029 offsets[num_offsets] = offset; limits[num_offsets] = limit;
3031 p += (n3 > 0 ? n3 : n1);
3036 time_t testtime = 0;
int testhour = 0;
3041 for (
unsigned i = 0; i < num_offsets; i++) {
3042 unsigned offset = offsets[i], limit = limits[i];
3044 if (0 < limit && limit < delay)
3049 int weekday = (tms->tm_wday ? tms->tm_wday : 7);
3050 for (
int j = 0; j <= maxtest; j++) {
3063 snprintf(pattern,
sizeof(pattern),
"%c/%02d/%02d/%1d/%02d",
3064 test_type_chars[j], tms->tm_mon+1, tms->tm_mday, weekday, tms->tm_hour);
3066 const unsigned len =
sizeof(
"S/01/01/1/01") - 1;
3067 snprintf(pattern + len,
sizeof(pattern) - len,
":%03u", offset);
3069 snprintf(pattern + len + 4,
sizeof(pattern) - len - 4,
"-%03u", limit);
3073 testtype = pattern[0];
3074 testtime = t; testhour = tms->tm_hour;
3088 if ((t += 3600) > now)
3099 if (!usetime && !(testhour == tmnow->tm_hour && testtime + 3600 > now)) {
3101 PrintOut(LOG_INFO,
"Device: %s, old test of type %c not run at %s, starting now.\n",
3102 cfg.
name.c_str(), testtype, datebuf);
3112 unsigned numdev = configs.size();
3117 PrintOut(LOG_INFO,
"\nNext scheduled self tests (at most 5 of each type per device):\n");
3120 time_t now = time(
nullptr);
3127 time_t testtime = now + seconds;
3128 for (
unsigned i = 0; i < numdev; i++) {
3138 PrintOut(LOG_INFO,
"Device: %s, will do test %d of type %c at %s\n", cfg.
name.c_str(),
3147 PrintOut(LOG_INFO,
"\nTotals [%s - %s]:\n", datenow, date);
3148 for (
unsigned i = 0; i < numdev; i++) {
3150 bool scsi =
devices.at(i)->is_scsi();
3155 PrintOut(LOG_INFO,
"Device: %s, will do %3d test%s of type %c\n", cfg.
name.c_str(),
3167 const char *testname =
nullptr;
3168 const char *name = cfg.
name.c_str();
3172 PrintOut(LOG_CRIT,
"Device: %s, does not support Self-Tests\n", name);
3177 if (1 == inProgress) {
3178 PrintOut(LOG_INFO,
"Device: %s, skip since Self-Test already in "
3179 "progress.\n", name);
3185 testname =
"Short Self";
3189 testname =
"Long Self";
3195 PrintOut(LOG_CRIT,
"Device: %s, not capable of %c Self-Test\n", name,
3202 PrintOut(LOG_CRIT,
"Device: %s, not capable of %s-Test\n", name,
3211 PrintOut(LOG_CRIT,
"Device: %s, execute %s-Test failed (err: %d)\n", name,
3216 PrintOut(LOG_INFO,
"Device: %s, starting scheduled %s-Test.\n", name, testname);
3225 const char *name = cfg.
name.c_str();
3230 PrintOut(LOG_CRIT,
"Device: %s, not capable of Offline or Self-Testing.\n", name);
3235 int dotest = -1, mode = 0;
3236 const char *testname =
nullptr;
3239 testname=
"Offline Immediate ";
3246 testname=
"Conveyance Self-";
3253 testname=
"Short Self-";
3260 testname=
"Long Self-";
3267 case 'c':
case 'n':
case 'r':
3268 testname =
"Selective Self-";
3284 PrintOut(LOG_CRIT,
"Device: %s, not capable of %sTest\n", name, testname);
3289 if (15==(
data.self_test_exec_status >> 4)) {
3291 PrintOut(LOG_INFO,
"Device: %s, will not skip scheduled %sTest "
3292 "despite unclear Self-Test byte (SAMSUNG Firmware bug).\n", name, testname);
3294 PrintOut(LOG_INFO,
"Device: %s, skip scheduled %sTest; %1d0%% remaining of current Self-Test.\n",
3295 name, testname, (
int)(
data.self_test_exec_status & 0x0f));
3309 PrintOut(LOG_CRIT,
"Device: %s, prepare %sTest failed\n", name, testname);
3313 PrintOut(LOG_INFO,
"Device: %s, %s test span at LBA %" PRIu64
" - %" PRIu64
" (%" PRIu64
" sectors, %u%% - %u%% of disk).\n",
3315 start, end, end - start + 1,
3325 PrintOut(LOG_CRIT,
"Device: %s, execute %sTest failed.\n", name, testname);
3331 if (testtype ==
'O')
3336 PrintOut(LOG_INFO,
"Device: %s, starting scheduled %sTest.\n", name, testname);
3342 unsigned char id,
bool increase_only,
3344 int mailtype,
const char * msg)
3360 if (!(!increase_only || prev_rawval < rawval))
3364 std::string
s =
strprintf(
"Device: %s, %" PRId64
" %s", cfg.
name.c_str(), rawval, msg);
3365 if (prev_rawval > 0 && rawval != prev_rawval)
3366 s +=
strprintf(
" (changed %+" PRId64
")", rawval - prev_rawval);
3374static const char *
fmt_temp(
unsigned char x,
char (& buf)[20])
3378 snprintf(buf,
sizeof(buf),
"%u", x);
3385 if (!(0 < currtemp && currtemp < 255)) {
3386 PrintOut(LOG_INFO,
"Device: %s, failed to read Temperature\n", cfg.
name.c_str());
3391 const char * minchg =
"", * maxchg =
"";
3392 if (currtemp > state.
tempmax) {
3405 PrintOut(LOG_INFO,
"Device: %s, initial Temperature is %d Celsius (Min/Max %s/%u%s)\n",
3408 PrintOut(LOG_INFO,
" [trip Temperature is %d Celsius]\n", (
int)triptemp);
3432 PrintOut(LOG_INFO,
"Device: %s, Temperature changed %+d Celsius to %u Celsius (Min/Max %s%s/%u%s)\n",
3440 PrintOut(LOG_CRIT,
"Device: %s, Temperature %u Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)\n",
3442 MailWarning(cfg, state, 12,
"Device: %s, Temperature %d Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)",
3446 PrintOut(LOG_INFO,
"Device: %s, Temperature %u Celsius reached limit of %u Celsius (Min/Max %s%s/%u%s)\n",
3451 if (currtemp < limit)
3452 reset_warning_mail(cfg, state, 12,
"Temperature %u Celsius dropped below %u Celsius", currtemp, limit);
3472 PrintOut(LOG_CRIT,
"Device: %s, Failed SMART usage Attribute: %d %s.\n", cfg.
name.c_str(), attr.
id, attrname.c_str());
3473 MailWarning(cfg, state, 2,
"Device: %s, Failed SMART usage Attribute: %d %s.", cfg.
name.c_str(), attr.
id, attrname.c_str());
3479 if (!( ( prefail && cfg.
prefail)
3480 || (!prefail && cfg.
usage )))
3488 if (attr.
id != prev.
id) {
3489 PrintOut(LOG_INFO,
"Device: %s, same Attribute has different ID numbers: %d = %d\n",
3490 cfg.
name.c_str(), attr.
id, prev.
id);
3495 bool valchanged =
false;
3502 bool rawchanged =
false;
3510 if (!(valchanged || rawchanged))
3514 std::string currstr, prevstr;
3536 std::string msg =
strprintf(
"Device: %s, SMART %s Attribute: %d %s changed from %s to %s",
3537 cfg.
name.c_str(), (prefail ?
"Prefailure" :
"Usage"), attr.
id,
3539 prevstr.c_str(), currstr.c_str());
3544 PrintOut(LOG_CRIT,
"%s\n", msg.c_str());
3548 PrintOut(LOG_INFO,
"%s\n", msg.c_str());
3555 bool firstpass,
bool allow_selftests)
3560 const char * name = cfg.
name.c_str();
3567 const char * mode = 0;
3568 if (0 <= powermode && powermode < 0xff) {
3573 if (powermode2 > powermode)
3574 PrintOut(LOG_INFO,
"Device: %s, CHECK POWER STATUS spins up disk (0x%02x -> 0x%02x)\n", name, powermode, powermode2);
3575 powermode = powermode2;
3627 mode=
"ACTIVE or IDLE";
3631 PrintOut(LOG_CRIT,
"Device: %s, CHECK POWER STATUS returned %d, not ATA compliant, ignoring -n Directive\n",
3644 PrintOut(LOG_INFO,
"Device: %s, is in %s mode, suspending checks\n", name, mode);
3651 PrintOut(LOG_INFO,
"Device: %s, %s mode ignored due to reached limit of skipped checks (%d check%s skipped)\n",
3658 PrintOut(LOG_INFO,
"Device: %s, is back in %s mode, resuming checks (%d check%s skipped)\n",
3669 PrintOut(LOG_INFO,
"Device: %s, not capable of SMART self-check\n",name);
3670 MailWarning(cfg, state, 5,
"Device: %s, not capable of SMART self-check", name);
3673 else if (status==1){
3674 PrintOut(LOG_CRIT,
"Device: %s, FAILED SMART self-check. BACK UP DATA NOW!\n", name);
3675 MailWarning(cfg, state, 1,
"Device: %s, FAILED SMART self-check. BACK UP DATA NOW!", name);
3689 PrintOut(LOG_CRIT,
"Device: %s, failed to read SMART Attribute Data\n", name);
3690 MailWarning(cfg, state, 6,
"Device: %s, failed to read SMART Attribute Data", name);
3700 :
"Total unreadable (pending) sectors" ));
3705 :
"Total offline uncorrectable sectors"));
3753 int errcnt1 = -1, errcnt2 = -1;
3760 int newc = (errcnt1 >= errcnt2 ? errcnt1 : errcnt2);
3765 MailWarning(cfg, state, 7,
"Device: %s, Read SMART Error Log Failed", name);
3770 PrintOut(LOG_CRIT,
"Device: %s, ATA error count increased from %d to %d\n",
3772 MailWarning(cfg, state, 4,
"Device: %s, ATA error count increased from %d to %d",
3800 const char * name = cfg.
name.c_str();
3802 uint8_t asc = 0, ascq = 0;
3803 uint8_t currenttemp = 0, triptemp = 0;
3806 &asc, &ascq, ¤ttemp, &triptemp)) {
3807 PrintOut(LOG_INFO,
"Device: %s, failed to read SMART values\n",
3809 MailWarning(cfg, state, 6,
"Device: %s, failed to read SMART values", name);
3818 PrintOut(LOG_CRIT,
"Device: %s, SMART Failure: %s\n", name, cp);
3819 MailWarning(cfg, state, 1,
"Device: %s, SMART Failure: %s", name, cp);
3820 }
else if (asc == 4 && ascq == 9) {
3821 PrintOut(LOG_INFO,
"Device: %s, self-test in progress\n", name);
3823 PrintOut(LOG_INFO,
"Device: %s, non-SMART asc,ascq: %d,%d\n",
3824 name, (
int)asc, (
int)ascq);
3826 PrintOut(LOG_INFO,
"Device: %s, SMART health: passed\n", name);
3882 const char * name = cfg.
name.c_str();
3888 PrintOut(LOG_INFO,
"Device: %s, failed to read NVMe SMART/Health Information\n", name);
3889 MailWarning(cfg, state, 6,
"Device: %s, failed to read NVMe SMART/Health Information", name);
3898 static const char *
const wnames[] =
3899 {
"LowSpare",
"Temperature",
"Reliability",
"R/O",
"VolMemBackup"};
3901 for (
unsigned b = 0, cnt = 0;
b < 8 ;
b++) {
3902 if (!(
w & (1 <<
b)))
3907 msg +=
"...";
break;
3909 if (
b >=
sizeof(wnames)/
sizeof(wnames[0])) {
3910 msg +=
"*Unknown*";
break;
3915 PrintOut(LOG_CRIT,
"Device: %s, Critical Warning (0x%02x): %s\n", name,
w, msg.c_str());
3916 MailWarning(cfg, state, 1,
"Device: %s, Critical Warning (0x%02x): %s", name,
w, msg.c_str());
3953 bool sts1 =
false, sts2 =
false;
3954 for (
const auto & cfg : configs) {
3955 if (cfg.offlinests_ns)
3957 if (cfg.selfteststs_ns)
3964 if (!
smi()->disable_system_auto_standby(
false)) {
3966 PrintOut(LOG_CRIT,
"System auto standby enable failed: %s\n",
smi()->get_errmsg());
3968 PrintOut(LOG_INFO,
"Disable auto standby not supported, ignoring ',ns' from %s%s%s\n",
3969 (sts1 ?
"-l offlinests,ns" :
""), (sts1 && sts2 ?
" and " :
""), (sts2 ?
"-l selfteststs,ns" :
""));
3970 sts1 = sts2 =
false;
3984 bool running =
false;
3985 for (
unsigned i = 0; i < configs.size() && !running; i++) {
4001 if (!
smi()->disable_system_auto_standby(
false))
4002 PrintOut(LOG_CRIT,
"Self-test(s) completed, system auto standby enable failed: %s\n",
4003 smi()->get_errmsg());
4005 PrintOut(LOG_INFO,
"Self-test(s) completed, system auto standby enabled\n");
4009 else if (!
smi()->disable_system_auto_standby(
true)) {
4011 PrintOut(LOG_INFO,
"Self-test(s) in progress, system auto standby disable rejected: %s\n",
4012 smi()->get_errmsg());
4018 PrintOut(LOG_INFO,
"Self-test(s) in progress, system auto standby disabled\n");
4028 for (
unsigned i = 0; i < configs.size(); i++) {
4033 PrintOut(LOG_INFO,
"Device: %s, skipped (interval=%d)\n", cfg.
name.c_str(),
4074static void ToggleDebugMode()
4077 PrintOut(LOG_INFO,
"Signal USR2 - enabling debug mode\n");
4078 if (!daemon_enable_console(
"smartd [Debug]")) {
4081 PrintOut(LOG_INFO,
"smartd debug mode enabled, PID=%d\n", getpid());
4084 PrintOut(LOG_INFO,
"enable console failed\n");
4087 daemon_disable_console();
4090 PrintOut(LOG_INFO,
"Signal USR2 - debug mode disabled\n");
4099 if (timenow < wakeuptime)
4101 return timenow + ct - (timenow - wakeuptime) % ct;
4108 time_t timenow = time(
nullptr);
4109 unsigned n = configs.size();
4119 for (
unsigned i = 0; i < n; i++) {
4125 if (!wakeuptime || state.
wakeuptime < wakeuptime)
4134 bool no_skip =
false;
4138 if (wakeuptime > timenow + ct) {
4139 PrintOut(LOG_INFO,
"System clock time adjusted to the past. Resetting next wakeup time.\n");
4140 wakeuptime = timenow + ct;
4141 for (
auto & state : states)
4142 state.wakeuptime = 0;
4147 sleep(wakeuptime+addtime-timenow);
4151 if (caughtsigUSR2) {
4157 timenow = time(
nullptr);
4160 if (!addtime && timenow > wakeuptime+60) {
4162 PrintOut(LOG_INFO,
"Sleep time was %d seconds too long, assuming wakeup from standby mode.\n",
4163 (
int)(timenow-wakeuptime));
4165 addtime = timenow-wakeuptime+20;
4167 int nextcheck = ct - addtime % ct;
4168 if (nextcheck <= 20)
4169 addtime += nextcheck;
4175 PrintOut(LOG_INFO,
"Signal USR1 - checking devices now rather than in %d seconds.\n",
4176 wakeuptime-timenow>0?(
int)(wakeuptime-timenow):0);
4178 sigwakeup = no_skip =
true;
4183 for (
auto & state : states)
4184 state.skip = (!no_skip && timenow < state.wakeuptime);
4196 PrintOut(priority,
"never[,N][,q], sleep[,N][,q], standby[,N][,q], idle[,N][,q]");
4199 PrintOut(priority,
"valid_regular_expression");
4202 PrintOut(priority,
"%s",
smi()->get_valid_dev_types_str().c_str());
4205 PrintOut(priority,
"normal, permissive");
4212 PrintOut(priority,
"error, selftest");
4215 PrintOut(priority,
"\"once\", \"always\", \"daily\", \"diminishing\", \"test\", \"exec\"");
4221 PrintOut(priority,
"use, ignore, show, showall");
4227 PrintOut(priority,
"aam,[N|off], apm,[N|off], lookahead,[on|off], dsn,[on|off] "
4228 "security-freeze, standby,[N|off], wcache,[on|off]");
4231 PrintOut(priority,
"i=N, interval=N");
4237static int GetInteger(
const char *arg,
const char *name,
const char *token,
int lineno,
const char *cfgfile,
4238 int min,
int max,
char * suffix = 0)
4242 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s takes integer argument from %d to %d.\n",
4243 cfgfile, lineno, name, token, min, max);
4249 int val = strtol(arg,&endptr,10);
4253 if (!strcmp(endptr, suffix))
4254 endptr += strlen(suffix);
4259 if (!(!*endptr && min <= val && val <= max)) {
4260 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s has argument: %s; needs integer from %d to %d.\n",
4261 cfgfile, lineno, name, token, arg, min, max);
4271static int Get3Integers(
const char *arg,
const char *name,
const char *token,
int lineno,
const char *cfgfile,
4272 unsigned char *val1,
unsigned char *val2,
unsigned char *val3)
4274 unsigned v1 = 0, v2 = 0, v3 = 0;
4275 int n1 = -1, n2 = -1, n3 = -1, len;
4277 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s takes 1-3 integer argument(s) from 0 to 255.\n",
4278 cfgfile, lineno, name, token);
4283 if (!( sscanf(arg,
"%u%n,%u%n,%u%n", &v1, &n1, &v2, &n2, &v3, &n3) >= 1
4284 && (n1 == len || n2 == len || n3 == len) && v1 <= 255 && v2 <= 255 && v3 <= 255)) {
4285 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s has argument: %s; needs 1-3 integer(s) from 0 to 255.\n",
4286 cfgfile, lineno, name, token, arg);
4289 *val1 = (
unsigned char)v1; *val2 = (
unsigned char)v2; *val3 = (
unsigned char)v3;
4297static const char * strtok_dequote(
const char * delimiters)
4299 const char * t = strtok(
nullptr, delimiters);
4300 if (!t || t[0] !=
'"')
4303 static std::string token;
4306 t = strtok(
nullptr, delimiters);
4310 int len = strlen(t);
4311 if (t[len-1] ==
'"') {
4312 token += std::string(t, len-1);
4317 return token.c_str();
4329 const char * name = cfg.
name.c_str();
4331 const char *delim =
" \n\t";
4334 const char *arg = 0;
4341 if (*token!=
'-' || strlen(token)!=2) {
4342 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): unknown Directive: %s\n",
4344 PrintOut(LOG_CRIT,
"Run smartd -D to print a list of valid Directives.\n");
4353 char plus[] =
"+", excl[] =
"!";
4358 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 0, 255, plus)) < 0)
4366 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 0, 255, plus)) < 0)
4374 if (!(arg = strtok(
nullptr, delim))) {
4376 }
else if (!strcmp(arg,
"normal")) {
4381 }
else if (!strcmp(arg,
"permissive")) {
4390 if (!(arg = strtok(
nullptr, delim))) {
4392 }
else if (!strcmp(arg,
"ignore")) {
4394 }
else if (!strcmp(arg,
"removable")) {
4396 }
else if (!strcmp(arg,
"auto")) {
4401 scan_types.push_back(arg);
4406 if (!(arg = strtok(
nullptr, delim)))
4434 if (!(arg = strtok(
nullptr, delim))) {
4436 }
else if (!strcmp(arg,
"selftest")) {
4439 }
else if (!strcmp(arg,
"error")) {
4442 }
else if (!strcmp(arg,
"xerror")) {
4445 }
else if (!strcmp(arg,
"offlinests")) {
4448 }
else if (!strcmp(arg,
"offlinests,ns")) {
4451 }
else if (!strcmp(arg,
"selfteststs")) {
4454 }
else if (!strcmp(arg,
"selfteststs,ns")) {
4457 }
else if (!strncmp(arg,
"scterc,",
sizeof(
"scterc,")-1)) {
4459 unsigned rt = ~0, wt = ~0;
int nc = -1;
4460 sscanf(arg,
"scterc,%u,%u%n", &rt, &wt, &nc);
4461 if (nc == (
int)strlen(arg) && rt <= 999 && wt <= 999) {
4484 if (!(arg = strtok(
nullptr, delim))) {
4486 }
else if (!strcmp(arg,
"on")) {
4488 }
else if (!strcmp(arg,
"off")) {
4496 if (!(arg = strtok(
nullptr, delim)))
4499 char *endptr =
nullptr;
4500 char *next = strchr(
const_cast<char*
>(arg),
',');
4507 if (!strcmp(arg,
"never"))
4509 else if (!strcmp(arg,
"sleep"))
4511 else if (!strcmp(arg,
"standby"))
4513 else if (!strcmp(arg,
"idle"))
4519 if (!badarg && next) {
4525 next = endptr + (*endptr !=
'\0');
4529 if (*next !=
'\0') {
4530 if (!strcmp(
"q", next))
4541 if (!(arg = strtok(
nullptr, delim))) {
4543 }
else if (!strcmp(arg,
"on")) {
4545 }
else if (!strcmp(arg,
"off")) {
4554 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous Test Directive -s %s\n",
4559 if (!(arg = strtok(
nullptr, delim))) {
4566 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): -s argument \"%s\" is INVALID extended regular expression. %s.\n",
4575 "[^]$()*+./:?^[|0-9LSCOncr-]+|"
4576 ":[0-9]{0,2}($|[^0-9])|:[0-9]{4,}|"
4577 ":[0-9]{3}-(000|[0-9]{0,2}($|[^0-9])|[0-9]{4,})"
4580 if (syntax_check.
execute(arg, 1, &range) && 0 <= range.rm_so && range.rm_so < range.rm_eo)
4581 PrintOut(LOG_INFO,
"File %s line %d (drive %s): warning, \"%.*s\" looks odd in "
4582 "extended regular expression \"%s\"\n",
4583 configfile, lineno, name, (
int)(range.rm_eo - range.rm_so), arg + range.rm_so, arg);
4588 if (!(arg = strtok(
nullptr, delim)))
4592 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous Address Directive -m %s\n",
4599 if (!(arg = strtok(
nullptr, delim)))
4601 else if (!strcmp(arg,
"once"))
4603 else if (!strcmp(arg,
"always"))
4605 else if (!strcmp(arg,
"daily"))
4607 else if (!strcmp(arg,
"diminishing"))
4609 else if (!strcmp(arg,
"test"))
4611 else if (!strcmp(arg,
"exec")) {
4615 arg = strtok_dequote(delim);
4616 if (arg && arg[0] ==
'"') {
4617 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive %s 'exec' argument: missing closing quote\n",
4622 arg = strtok(
nullptr, delim);
4625 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive %s 'exec' argument must be followed by executable path.\n",
4631 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous mail Directive -M exec %s\n",
4640 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255)) < 0)
4646 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255)) < 0)
4652 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255, excl)) < 0)
4660 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255, excl)) < 0)
4674 if (!(arg = strtok(
nullptr, delim))) {
4682 if (!(arg = strtok(
nullptr, delim))) {
4684 }
else if (!strcmp(arg,
"use")) {
4686 }
else if (!strcmp(arg,
"ignore")) {
4688 }
else if (!strcmp(arg,
"show")) {
4690 }
else if (!strcmp(arg,
"showall")) {
4699 if (!(arg = strtok(
nullptr, delim))) {
4703 char arg2[16+1];
unsigned uval;
4704 int n1 = -1, n2 = -1, n3 = -1, len = strlen(arg);
4705 if (sscanf(arg,
"%16[^,=]%n%*[,=]%n%u%n", arg2, &n1, &n2, &uval, &n3) >= 1
4706 && (n1 == len || n2 > 0)) {
4707 bool on = (n2 > 0 && !strcmp(arg+n2,
"on"));
4708 bool off = (n2 > 0 && !strcmp(arg+n2,
"off"));
4712 if (!strcmp(arg2,
"aam")) {
4715 else if (uval <= 254)
4720 else if (!strcmp(arg2,
"apm")) {
4723 else if (1 <= uval && uval <= 254)
4728 else if (!strcmp(arg2,
"lookahead")) {
4736 else if (!strcmp(arg,
"security-freeze")) {
4739 else if (!strcmp(arg2,
"standby")) {
4742 else if (uval <= 255)
4747 else if (!strcmp(arg2,
"wcache")) {
4755 else if (!strcmp(arg2,
"dsn")) {
4774 if (!(arg = strtok(
nullptr, delim))) {
4778 int n = 0, nc = -1, len = strlen(arg);
4779 if ( ( sscanf(arg,
"i=%d%n", &n, &nc) == 1
4780 || sscanf(arg,
"interval=%d%n", &n, &nc) == 1)
4781 && nc == len && n >= 10)
4790 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): unknown Directive: %s\n",
4792 PrintOut(LOG_CRIT,
"Run smartd -D to print a list of valid Directives.\n");
4796 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Missing argument to %s Directive\n",
4800 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Invalid argument to %s Directive: %s\n",
4803 if (missingarg || badarg) {
4804 PrintOut(LOG_CRIT,
"Valid arguments to %s Directive are: ", token);
4814#define SCANDIRECTIVE "DEVICESCAN"
4828 const char *delim =
" \n\t";
4831 const char * name = strtok(line, delim);
4832 if (!name || *name ==
'#')
4837 if (!strcmp(
"DEFAULT", name)) {
4845 conf_entries.push_back(default_conf);
4847 dev_config & cfg = (retval ? conf_entries.back() : default_conf);
4854 while (
char * token = strtok(
nullptr, delim)) {
4868 if (retval != -1 && scan_types.size() > 1) {
4869 PrintOut(LOG_CRIT,
"Drive: %s, invalid multiple -d TYPE Directives on line %d of file %s\n",
4885 PrintOut(LOG_INFO,
"Drive: %s, implied '-a' Directive on line %d of file %s\n",
4900 PrintOut(LOG_CRIT,
"Drive: %s, -M Directive(s) on line %d of file %s need -m ADDRESS Directive\n",
4909 PrintOut(LOG_CRIT,
"Drive: %s, -m <nomailer> Directive on line %d of file %s needs -M exec Directive\n",
4934 const int MAXLINELEN = 256;
4936 const int MAXCONTLINE = 1023;
4943 int ret = (errno!=ENOENT ? -3 : -2);
4944 PrintOut(LOG_CRIT,
"%s: Unable to open configuration file %s\n",
4960 if (
ParseConfigLine(conf_entries, default_conf, scan_types, 0, fakeconfig) != -1)
4961 throw std::logic_error(
"Internal error parsing " SCANDIRECTIVE);
4966 setmode(fileno(f), O_TEXT);
4973 int lineno = 1, cont = 0, contlineno = 0;
4974 char line[MAXLINELEN+2];
4975 char fullline[MAXCONTLINE+1];
4978 int len=0,scandevice;
4984 memset(line,0,
sizeof(line));
4987 code=fgets(line, MAXLINELEN+2, f);
4992 scandevice =
ParseConfigLine(conf_entries, default_conf, scan_types, contlineno, fullline);