13#define __STDC_FORMAT_MACROS 1
46#include "os_win32/popen.h"
48#pragma warning(disable:4761)
49typedef unsigned short mode_t;
65#include <systemd/sd-daemon.h>
82#include "os_win32/daemon_win32.h"
83#define strsignal daemon_strsignal
84#define sleep daemon_sleep
86#define SIGQUIT SIGBREAK
87#define SIGQUIT_KEYNAME "CONTROL-Break"
89#define SIGQUIT_KEYNAME "CONTROL-\\"
103 daemon_signal(sig, handler);
105#elif defined(HAVE_SIGACTION)
108 sa.sa_handler = SIG_DFL;
109 sigaction(sig, (
struct sigaction *)0, &sa);
110 if (sa.sa_handler == SIG_IGN)
113 memset(&sa, 0,
sizeof(sa));
114 sa.sa_handler = handler;
115 sa.sa_flags = SA_RESTART;
116 sigaction(sig, &sa, (
struct sigaction *)0);
118#elif defined(HAVE_SIGSET)
120 if (sigset(sig, handler) == SIG_IGN)
121 sigset(sig, SIG_IGN);
127 if (signal(sig, handler) == SIG_IGN)
128 signal(sig, SIG_IGN);
138#define EXIT_BADCONF 2
139#define EXIT_STARTUP 3
142#define EXIT_READCONF 6
145#define EXIT_BADCODE 10
147#define EXIT_BADDEV 16
150#define EXIT_SIGNAL 254
166#ifdef SMARTMONTOOLS_SAVESTATES
167 = SMARTMONTOOLS_SAVESTATES
173#ifdef SMARTMONTOOLS_ATTRIBUTELOG
174 = SMARTMONTOOLS_ATTRIBUTELOG
190static bool warn_as_user;
191static uid_t warn_uid;
192static gid_t warn_gid;
193static std::string warn_uname, warn_gname;
196static bool warn_as_restr_user;
223static volatile int caughtsigUSR2=0;
234static void PrintOut(
int priority,
const char *
fmt, ...)
237#ifdef HAVE_LIBSYSTEMD
240static bool notify_enabled =
false;
241static bool notify_ready =
false;
245 if (!getenv(
"NOTIFY_SOCKET"))
247 notify_enabled =
true;
255 PrintOut(LOG_CRIT,
"Option -n (--no-fork) is required if 'Type=notify' is set.\n");
267 const char * notify =
"EXTEND_TIMEOUT_USEC=20000000";
269 pout(
"sd_notify(0, \"%s\")\n", notify);
272 sd_notify(0, notify);
275static void notify_msg(
const char * msg,
bool ready =
false)
280 pout(
"sd_notify(0, \"%sSTATUS=%s\")\n", (ready ?
"READY=1\\n" :
""), msg);
283 sd_notifyf(0,
"%sSTATUS=%s", (ready ?
"READY=1\n" :
""), msg);
291 snprintf(msg,
sizeof(msg),
"Checking %d device%s ...",
292 numdev, (numdev != 1 ?
"s" :
""));
296static void notify_wait(time_t wakeuptime,
int numdev)
300 char ts[16] =
"";
struct tm tmbuf;
303 snprintf(msg,
sizeof(msg),
"Next check of %d device%s will start at %s",
304 numdev, (numdev != 1 ?
"s" :
""), ts);
315 case 0: msg =
"Exiting ...";
break;
316 case EXIT_BADCMD: msg =
"Error in command line (see SYSLOG)";
break;
318 case EXIT_READCONF: msg =
"Error in config file (see SYSLOG)";
break;
319 case EXIT_BADDEV: msg =
"Unable to register a device (see SYSLOG)";
break;
320 case EXIT_NODEV: msg =
"No devices to monitor";
break;
321 default: msg =
"Error (see SYSLOG)";
break;
334 if (getenv(
"NOTIFY_SOCKET")) {
335 PrintOut(LOG_CRIT,
"This version of smartd was build without 'Type=notify' support.\n");
371 bool is_set(
int id,
unsigned char flag)
const
372 {
return (0 <
id &&
id < (
int)
sizeof(
m_flags) && (
m_flags[
id] & flag)); }
376 if (0 <
id &&
id < (
int)
sizeof(
m_flags))
592 | ((uint64_t)ta.
raw[3] << 24)
593 | ((uint64_t)ta.
raw[4] << 32)
594 | ((uint64_t)ta.
raw[5] << 40);
608 memset(ta.
raw, 0,
sizeof(ta.
raw));
613 ta.
raw[0] = (
unsigned char) pa.
raw;
614 ta.
raw[1] = (
unsigned char)(pa.
raw >> 8);
615 ta.
raw[2] = (
unsigned char)(pa.
raw >> 16);
616 ta.
raw[3] = (
unsigned char)(pa.
raw >> 24);
617 ta.
raw[4] = (
unsigned char)(pa.
raw >> 32);
618 ta.
raw[5] = (
unsigned char)(pa.
raw >> 40);
630 "|(self-test-errors)"
631 "|(self-test-last-err-hour)"
632 "|(scheduled-test-next-check)"
633 "|(selective-test-last-start)"
634 "|(selective-test-last-end)"
636 "|(mail\\.([0-9]+)\\."
642 "|(ata-smart-attribute\\.([0-9]+)\\."
650 "|(nvme-err-log-entries)"
652 " *= *([0-9]+)[ \n]*$"
655 const int nmatch = 1+25;
659 if (
match[nmatch-1].rm_so < 0)
662 uint64_t val = strtoull(line +
match[nmatch-1].rm_so, (
char **)0, 10);
665 if (
match[++m].rm_so >= 0)
666 state.
tempmin = (
unsigned char)val;
667 else if (
match[++m].rm_so >= 0)
668 state.
tempmax = (
unsigned char)val;
669 else if (
match[++m].rm_so >= 0)
671 else if (
match[++m].rm_so >= 0)
673 else if (
match[++m].rm_so >= 0)
675 else if (
match[++m].rm_so >= 0)
677 else if (
match[++m].rm_so >= 0)
679 else if (
match[++m].rm_so >= 0)
681 else if (
match[m+=2].rm_so >= 0) {
682 int i = atoi(line+
match[m].rm_so);
687 if (
match[m+=2].rm_so >= 0)
689 else if (
match[++m].rm_so >= 0)
691 else if (
match[++m].rm_so >= 0)
696 else if (
match[m+=5+1].rm_so >= 0) {
697 int i = atoi(line+
match[m].rm_so);
700 if (
match[m+=2].rm_so >= 0)
702 else if (
match[++m].rm_so >= 0)
704 else if (
match[++m].rm_so >= 0)
706 else if (
match[++m].rm_so >= 0)
708 else if (
match[++m].rm_so >= 0)
713 else if (
match[m+7].rm_so >= 0)
726 pout(
"Cannot read state file \"%s\"\n", path);
730 setmode(fileno(f), O_TEXT);
734 int good = 0, bad = 0;
736 while (fgets(line,
sizeof(line), f)) {
737 const char *
s = line + strspn(line,
" \t");
738 if (!*
s || *
s ==
'#')
748 pout(
"%s: format error\n", path);
751 pout(
"%s: %d invalid line(s) ignored\n", path, bad);
762 fprintf(f,
"%s = %" PRIu64
"\n", name, val);
768 fprintf(f,
"%s.%d.%s = %" PRIu64
"\n", name1,
id, name2, val);
775 std::string pathbak = path; pathbak +=
'~';
776 unlink(pathbak.c_str());
777 rename(path, pathbak.c_str());
781 pout(
"Cannot create state file \"%s\"\n", path);
785 fprintf(f,
"# smartd state file\n");
830 pout(
"Cannot create attribute log file \"%s\"\n", path);
835 time_t now = time(
nullptr);
837 fprintf(f,
"%d-%02d-%02d %02d:%02d:%02d;",
838 1900+tms->tm_year, 1+tms->tm_mon, tms->tm_mday,
839 tms->tm_hour, tms->tm_min, tms->tm_sec);
844 fprintf(f,
"\t%d;%d;%" PRIu64
";", pa.id, pa.val, pa.raw);
848 const char * pageNames[3] = {
"read",
"write",
"verify"};
849 for (
int k = 0; k < 3; ++k) {
852 fprintf(f,
"\t%s-corr-by-ecc-fast;%" PRIu64
";"
853 "\t%s-corr-by-ecc-delayed;%" PRIu64
";"
854 "\t%s-corr-by-retry;%" PRIu64
";"
855 "\t%s-total-err-corrected;%" PRIu64
";"
856 "\t%s-corr-algorithm-invocations;%" PRIu64
";"
857 "\t%s-gb-processed;%.3f;"
858 "\t%s-total-unc-errors;%" PRIu64
";",
864 pageNames[k], (ecp->
counter[5] / 1000000000.0),
865 pageNames[k], ecp->
counter[6]);
872 fprintf(f,
"\ttemperature;%d;", state.
temperature);
882 bool write_always =
true)
884 for (
unsigned i = 0; i < states.size(); i++) {
895 PrintOut(LOG_INFO,
"Device: %s, state written to %s\n",
904 for (
unsigned i = 0; i < states.size(); i++) {
928static void USR2handler(
int sig)
959static int capabilities_mode ;
963 if (!capabilities_mode)
965 capng_clear(CAPNG_SELECT_BOTH);
966 capng_updatev(CAPNG_ADD, (capng_type_t)(CAPNG_EFFECTIVE|CAPNG_PERMITTED),
967 CAP_SYS_ADMIN, CAP_MKNOD, CAP_SYS_RAWIO, -1);
968 if (warn_as_user && (warn_uid || warn_gid)) {
970 capng_updatev(CAPNG_ADD, (capng_type_t)(CAPNG_EFFECTIVE|CAPNG_PERMITTED),
971 CAP_SETGID, CAP_SETUID, -1);
973 if (capabilities_mode > 1) {
975 capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET,
976 CAP_SETGID, CAP_SETUID, CAP_CHOWN, CAP_FOWNER, CAP_DAC_OVERRIDE, -1);
978 capng_apply(CAPNG_SELECT_BOTH);
983 if (!capabilities_mode)
985 PrintOut(LOG_INFO,
"If mail notification does not work with '--capabilities%s\n",
986 (capabilities_mode == 1 ?
"', try '--capabilities=mail'"
987 :
"=mail', please inform " PACKAGE_BUGREPORT));
1015 void set(
const char * name,
const char * value);
1022 int size = strlen(name) + 1 + strlen(value) + 1;
1023 char * newbuf =
new char[
size];
1024 snprintf(newbuf,
size,
"%s=%s", name, value);
1027 throw std::runtime_error(
"putenv() failed");
1048 static const char *
const whichfail[] = {
1054 "FailedHealthCheck",
1055 "FailedReadSmartData",
1056 "FailedReadSmartErrorLog",
1057 "FailedReadSmartSelfTestLog",
1059 "CurrentPendingSector",
1060 "OfflineUncorrectableSector",
1066 PrintOut(LOG_CRIT,
"Internal error in MailWarning(): which=%d\n", which);
1074 days = nextdays = -1;
1077 days = nextdays = -1;
break;
1079 days = nextdays = 0;
break;
1081 days = nextdays = 1;
break;
1084 nextdays = 1 << ((unsigned)mail->
logged <= 5 ? mail->
logged : 5);
1086 days = ((unsigned)mail->
logged <= 5 ? nextdays >> 1 : nextdays);
1089 PrintOut(LOG_CRIT,
"Internal error in MailWarning(): cfg.emailfreq=%d\n", (
int)cfg.
emailfreq);
1093 time_t now = time(
nullptr);
1098 if (days > 0 && now < mail->lastsent + days * 24 * 3600)
1122 std::replace(address.begin(), address.end(),
',',
' ');
1128 env[0].
set(
"SMARTD_MAILER", executable);
1129 env[1].
set(
"SMARTD_MESSAGE", message);
1131 snprintf(dates,
sizeof(dates),
"%d", mail->
logged);
1132 env[2].
set(
"SMARTD_PREVCNT", dates);
1134 env[3].
set(
"SMARTD_TFIRST", dates);
1136 env[4].
set(
"SMARTD_TFIRSTEPOCH", dates);
1137 env[5].
set(
"SMARTD_FAILTYPE", whichfail[which]);
1138 env[6].
set(
"SMARTD_ADDRESS", address.c_str());
1139 env[7].
set(
"SMARTD_DEVICESTRING", cfg.
name.c_str());
1142 env[8].
set(
"SMARTD_DEVICETYPE",
1144 env[9].
set(
"SMARTD_DEVICE", cfg.
dev_name.c_str());
1149 snprintf(dates,
sizeof(dates),
"%d", nextdays);
1150 env[11].
set(
"SMARTD_NEXTDAYS", dates);
1152 env[12].
set(
"SMARTD_SUBJECT",
"");
1156 executable =
"<mail>";
1157 const char * newadd = (!address.empty()? address.c_str() :
"<nomailer>");
1158 const char * newwarn = (which?
"Warning via" :
"Test of");
1163 snprintf(command,
sizeof(command),
"\"%s\" 2>&1",
warning_script.c_str());
1165 snprintf(command,
sizeof(command),
"%s 2>&1",
warning_script.c_str());
1169 PrintOut(LOG_INFO,
"%s %s to %s%s ...\n",
1170 (which ?
"Sending warning via" :
"Executing test of"), executable, newadd,
1172#ifdef HAVE_POSIX_API
1175 (
unsigned)warn_uid, warn_uname.c_str(),
1176 (
unsigned)warn_gid, warn_gname.c_str() ).c_str() :
1178 warn_as_restr_user ?
" (restricted user)" :
1188#ifdef HAVE_POSIX_API
1195 pfp = popen_as_restr_user(command,
"r", warn_as_restr_user);
1197 pfp = popen(command,
"r");
1203 PrintOut(LOG_CRIT,
"%s %s to %s: failed (fork or pipe failed, or no memory) %s\n",
1204 newwarn, executable, newadd, errno?strerror(errno):
"");
1215 PrintOut(LOG_CRIT,
"%s %s to %s produced unexpected output (%s%d bytes) to STDOUT/STDERR: \n%s\n",
1216 newwarn, executable, newadd, len!=newlen?
"here truncated to ":
"", newlen,
buffer);
1224 PrintOut(LOG_CRIT,
"%s %s to %s: flushed remaining STDOUT/STDERR\n",
1225 newwarn, executable, newadd);
1227 PrintOut(LOG_CRIT,
"%s %s to %s: more than 1 MB STDOUT/STDERR flushed, breaking pipe\n",
1228 newwarn, executable, newadd);
1235#ifdef HAVE_POSIX_API
1241 status = pclose(pfp);
1245 PrintOut(LOG_CRIT,
"%s %s to %s: pclose(3) failed %s\n", newwarn, executable, newadd,
1246 errno?strerror(errno):
"");
1249 if (WIFEXITED(status)) {
1251 int status8 = WEXITSTATUS(status);
1253 PrintOut(LOG_CRIT,
"%s %s to %s: failed (32-bit/8-bit exit status: %d/%d) perhaps caught signal %d [%s]\n",
1254 newwarn, executable, newadd, status, status8, status8-128, strsignal(status8-128));
1256 PrintOut(LOG_CRIT,
"%s %s to %s: failed (32-bit/8-bit exit status: %d/%d)\n",
1257 newwarn, executable, newadd, status, status8);
1261 PrintOut(LOG_INFO,
"%s %s to %s: successful\n", newwarn, executable, newadd);
1264 if (WIFSIGNALED(status))
1265 PrintOut(LOG_INFO,
"%s %s to %s: exited because of uncaught signal %d [%s]\n",
1266 newwarn, executable, newadd, WTERMSIG(status), strsignal(WTERMSIG(status)));
1270 if (WIFSTOPPED(status))
1271 PrintOut(LOG_CRIT,
"%s %s to %s: process STOPPED because it caught signal %d [%s]\n",
1272 newwarn, executable, newadd, WSTOPSIG(status), strsignal(WSTOPSIG(status)));
1301 PrintOut(LOG_INFO,
"Device: %s, %s, warning condition reset after %d email%s\n", cfg.
name.c_str(),
1313static
void vsyslog_lines(
int priority, const
char *
fmt, va_list
ap)
1318 for (
char * p = buf, * q; p && *p; p = q) {
1319 if ((q = strchr(p,
'\n')))
1322 syslog(priority,
"%s\n", p);
1328#define vsyslog_lines vsyslog
1352 vfprintf(f,
fmt,
ap);
1357 openlog(
"smartd", LOG_PID,
facility);
1358 vsyslog_lines(LOG_INFO,
fmt,
ap);
1379 vfprintf(f,
fmt,
ap);
1383 openlog(
"smartd", LOG_PID,
facility);
1384 vsyslog_lines(priority,
fmt,
ap);
1394 pout(
"Warning! %s error: invalid SMART checksum.\n",
string);
1403 int waited, max_wait = 10;
1404 struct stat stat_buf;
1409 for(waited = 0; waited < max_wait; ++waited) {
1410 if (!stat(
pid_file.c_str(), &stat_buf)) {
1434 if ((pid=fork()) < 0) {
1436 PrintOut(LOG_CRIT,
"smartd unable to fork daemon process!\n");
1452 if ((pid=fork()) < 0) {
1454 PrintOut(LOG_CRIT,
"smartd unable to fork daemon process!\n");
1465 int open_max = sysconf(_SC_OPEN_MAX);
1466#ifdef HAVE_CLOSE_RANGE
1467 if (close_range(0, open_max - 1, 0))
1472 for (
int i = 0, failed = 0; i < open_max && failed < 1024; i++)
1473 failed = (!close(i) ? 0 : failed + 1);
1477 int fd = open(
"/dev/null", O_RDWR);
1478 if (!(fd == 0 && dup(fd) == 1 && dup(fd) == 2 && !chdir(
"/"))) {
1479 PrintOut(LOG_CRIT,
"smartd unable to redirect to /dev/null or to chdir to root!\n");
1485 PrintOut(LOG_INFO,
"smartd has fork()ed into background mode. New PID=%d.\n", (
int)getpid());
1492 if (daemon_detach(
"smartd")) {
1493 PrintOut(LOG_CRIT,
"smartd unable to detach from console!\n");
1508 pid_t pid = getpid();
1511 old_umask = umask(0077);
1514 old_umask = umask(0033);
1519 if (!(f && fprintf(f,
"%d\n", (
int)pid) > 0 && f.
close())) {
1520 PrintOut(LOG_CRIT,
"unable to write PID file %s - exiting.\n",
pid_file.c_str());
1523 PrintOut(LOG_INFO,
"file %s written containing PID %d\n",
pid_file.c_str(), (
int)pid);
1538 "Configuration file (%s) Directives (after device name):\n"
1539 " -d TYPE Set the device type: auto, ignore, removable,\n"
1541 " -T TYPE Set the tolerance to one of: normal, permissive\n"
1542 " -o VAL Enable/disable automatic offline tests (on/off)\n"
1543 " -S VAL Enable/disable attribute autosave (on/off)\n"
1544 " -n MODE No check if: never, sleep[,N][,q], standby[,N][,q], idle[,N][,q]\n"
1545 " -H Monitor SMART Health Status, report if failed\n"
1546 " -s REG Do Self-Test at time(s) given by regular expression REG\n"
1547 " -l TYPE Monitor SMART log or self-test status:\n"
1548 " error, selftest, xerror, offlinests[,ns], selfteststs[,ns]\n"
1549 " -l scterc,R,W Set SCT Error Recovery Control\n"
1550 " -e Change device setting: aam,[N|off], apm,[N|off], dsn,[on|off],\n"
1551 " lookahead,[on|off], security-freeze, standby,[N|off], wcache,[on|off]\n"
1552 " -f Monitor 'Usage' Attributes, report failures\n"
1553 " -m ADD Send email warning to address ADD\n"
1554 " -M TYPE Modify email warning behavior (see man page)\n"
1555 " -p Report changes in 'Prefailure' Attributes\n"
1556 " -u Report changes in 'Usage' Attributes\n"
1557 " -t Equivalent to -p and -u Directives\n"
1558 " -r ID Also report Raw values of Attribute ID with -p, -u or -t\n"
1559 " -R ID Track changes in Attribute ID Raw value with -p, -u or -t\n"
1560 " -i ID Ignore Attribute ID for -f Directive\n"
1561 " -I ID Ignore Attribute ID for -p, -u or -t Directive\n"
1562 " -C ID[+] Monitor [increases of] Current Pending Sectors in Attribute ID\n"
1563 " -U ID[+] Monitor [increases of] Offline Uncorrectable Sectors in Attribute ID\n"
1564 " -W D,I,C Monitor Temperature D)ifference, I)nformal limit, C)ritical limit\n"
1565 " -v N,ST Modifies labeling of Attribute N (see man page) \n"
1566 " -P TYPE Drive-specific presets: use, ignore, show, showall\n"
1567 " -a Default: -H -f -t -l error -l selftest -l selfteststs -C 197 -U 198\n"
1568 " -F TYPE Use firmware bug workaround:\n"
1570 " -c i=N Set interval between disk checks to N seconds\n"
1571 " # Comment: text after a hash sign is ignored\n"
1572 " \\ Line continuation character\n"
1573 "Attribute ID is a decimal integer 1 <= ID <= 255\n"
1574 "Use ID = 0 to turn off -C and/or -U Directives\n"
1575 "Example: /dev/sda -a\n",
1577 smi()->get_valid_dev_types_str().c_str(),
1588 return "<PATH_PREFIX>, -";
1590 return "[+]<FILE_NAME>";
1592 return "<FILE_NAME>, -";
1594 return "daemon, local0, local1, local2, local3, local4, local5, local6, local7";
1596 return "nodev[0], errors[,nodev0], nodev[0]startup, never, onecheck, showtests";
1598 return "ioctl[,N], ataioctl[,N], scsiioctl[,N], nvmeioctl[,N]";
1601 return "<FILE_NAME>";
1603 return "<INTEGER_SECONDS>";
1604#ifdef HAVE_POSIX_API
1606 return "<USER>[:<GROUP>], -";
1607#elif defined(_WIN32)
1609 return "restricted, unchanged";
1611#ifdef HAVE_LIBCAP_NG
1613 return "mail, <no_argument>";
1623 PrintOut(LOG_INFO,
"Usage: smartd [options]\n\n");
1624#ifdef SMARTMONTOOLS_ATTRIBUTELOG
1625 PrintOut(LOG_INFO,
" -A PREFIX|-, --attributelog=PREFIX|-\n");
1627 PrintOut(LOG_INFO,
" -A PREFIX, --attributelog=PREFIX\n");
1629 PrintOut(LOG_INFO,
" Log attribute information to {PREFIX}MODEL-SERIAL.TYPE.csv\n");
1630#ifdef SMARTMONTOOLS_ATTRIBUTELOG
1631 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_ATTRIBUTELOG
"MODEL-SERIAL.TYPE.csv]\n");
1634 PrintOut(LOG_INFO,
" -B [+]FILE, --drivedb=[+]FILE\n");
1635 PrintOut(LOG_INFO,
" Read and replace [add] drive database from FILE\n");
1637#ifdef SMARTMONTOOLS_DRIVEDBDIR
1639 PrintOut(LOG_INFO,
" and then %s", get_drivedb_path_default());
1642 PrintOut(LOG_INFO,
" -c NAME|-, --configfile=NAME|-\n");
1643 PrintOut(LOG_INFO,
" Read configuration file NAME or stdin\n");
1645#ifdef HAVE_LIBCAP_NG
1646 PrintOut(LOG_INFO,
" -C, --capabilities[=mail]\n");
1647 PrintOut(LOG_INFO,
" Drop unneeded Linux process capabilities.\n"
1648 " Warning: Mail notification may not work when used.\n\n");
1650 PrintOut(LOG_INFO,
" -d, --debug\n");
1651 PrintOut(LOG_INFO,
" Start smartd in debug mode\n\n");
1652 PrintOut(LOG_INFO,
" -D, --showdirectives\n");
1653 PrintOut(LOG_INFO,
" Print the configuration file Directives and exit\n\n");
1654 PrintOut(LOG_INFO,
" -h, --help, --usage\n");
1655 PrintOut(LOG_INFO,
" Display this help and exit\n\n");
1656 PrintOut(LOG_INFO,
" -i N, --interval=N\n");
1657 PrintOut(LOG_INFO,
" Set interval between disk checks to N seconds, where N >= 10\n\n");
1658 PrintOut(LOG_INFO,
" -l local[0-7], --logfacility=local[0-7]\n");
1660 PrintOut(LOG_INFO,
" Use syslog facility local0 - local7 or daemon [default]\n\n");
1662 PrintOut(LOG_INFO,
" Log to \"./smartd.log\", stdout, stderr [default is event log]\n\n");
1665 PrintOut(LOG_INFO,
" -n, --no-fork\n");
1666 PrintOut(LOG_INFO,
" Do not fork into background\n");
1667#ifdef HAVE_LIBSYSTEMD
1668 PrintOut(LOG_INFO,
" (systemd 'Type=notify' is assumed if $NOTIFY_SOCKET is set)\n");
1672 PrintOut(LOG_INFO,
" -p NAME, --pidfile=NAME\n");
1673 PrintOut(LOG_INFO,
" Write PID file NAME\n\n");
1674 PrintOut(LOG_INFO,
" -q WHEN, --quit=WHEN\n");
1676 PrintOut(LOG_INFO,
" -r, --report=TYPE\n");
1678#ifdef SMARTMONTOOLS_SAVESTATES
1679 PrintOut(LOG_INFO,
" -s PREFIX|-, --savestates=PREFIX|-\n");
1681 PrintOut(LOG_INFO,
" -s PREFIX, --savestates=PREFIX\n");
1683 PrintOut(LOG_INFO,
" Save disk states to {PREFIX}MODEL-SERIAL.TYPE.state\n");
1684#ifdef SMARTMONTOOLS_SAVESTATES
1685 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_SAVESTATES
"MODEL-SERIAL.TYPE.state]\n");
1688 PrintOut(LOG_INFO,
" -w NAME, --warnexec=NAME\n");
1689 PrintOut(LOG_INFO,
" Run executable NAME on warnings\n");
1691 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_SMARTDSCRIPTDIR
"/smartd_warning.sh]\n\n");
1695#ifdef HAVE_POSIX_API
1696 PrintOut(LOG_INFO,
" -u USER[:GROUP], --warn-as-user=USER[:GROUP]\n");
1697 PrintOut(LOG_INFO,
" Run warning script as non-privileged USER\n\n");
1698#elif defined(_WIN32)
1699 PrintOut(LOG_INFO,
" -u MODE, --warn-as-user=MODE\n");
1704 PrintOut(LOG_INFO,
" Running as windows service (see man page), install with:\n");
1705 PrintOut(LOG_INFO,
" smartd install [options]\n");
1706 PrintOut(LOG_INFO,
" Remove service with:\n");
1707 PrintOut(LOG_INFO,
" smartd remove\n\n");
1709 PrintOut(LOG_INFO,
" -V, --version, --license, --copyright\n");
1710 PrintOut(LOG_INFO,
" Print License, Copyright, and version information\n");
1715 if (!device->
close()){
1726 bool changed =
false;
1727 for (
unsigned i = 0; i <
s.size(); i++) {
1731 if ((
' ' <= c && c <=
'~') && !(i == 0 && c ==
'~'))
1742 return !( (
'0' <= c && c <=
'9')
1743 || (
'A' <= c && c <=
'Z')
1744 || (
'a' <= c && c <=
'z'));
1755 PrintOut(LOG_INFO,
"Device: %s, Read Summary SMART Error Log failed\n",name);
1763 PrintOut(LOG_INFO,
"Device: %s, Read Extended Comprehensive SMART Error Log failed\n",name);
1779 PrintOut(LOG_INFO,
"Device: %s, Read SMART Self Test Log Failed\n",name);
1788 int errcnt = 0, hours = 0;
1789 for (
int i = 20; i >= 0; i--) {
1795 int status =
entry.selfteststatus >> 4;
1796 if (status == 0x0 && (
entry.selftestnumber & 0x7f) == 0x02)
1800 if (0x3 <= status && status <= 0x8) {
1805 hours =
entry.timestamp;
1809 return ((hours << 8) | errcnt);
1812#define SELFTEST_ERRORCOUNT(x) (x & 0xff)
1813#define SELFTEST_ERRORHOURS(x) ((x >> 8) & 0xffff)
1818 return ((status & 0x7f) == 0x03);
1824 return ((status >> 4) == 0xf);
1831 switch (status & 0x7f) {
1832 case 0x00: msg =
"was never started";
break;
1833 case 0x02: msg =
"was completed without error";
break;
1834 case 0x03: msg =
"is in progress";
break;
1835 case 0x04: msg =
"was suspended by an interrupting command from host";
break;
1836 case 0x05: msg =
"was aborted by an interrupting command from host";
break;
1837 case 0x06: msg =
"was aborted by the device with a fatal error";
break;
1838 default: msg =
nullptr;
1842 PrintOut(((status & 0x7f) == 0x06 ? LOG_CRIT : LOG_INFO),
1843 "Device: %s, offline data collection %s%s\n", name, msg,
1844 ((status & 0x80) ?
" (auto:on)" :
""));
1846 PrintOut(LOG_INFO,
"Device: %s, unknown offline data collection status 0x%02x\n",
1854 switch (status >> 4) {
1855 case 0x0: msg =
"completed without error";
break;
1856 case 0x1: msg =
"was aborted by the host";
break;
1857 case 0x2: msg =
"was interrupted by the host with a reset";
break;
1858 case 0x3: msg =
"could not complete due to a fatal or unknown error";
break;
1859 case 0x4: msg =
"completed with error (unknown test element)";
break;
1860 case 0x5: msg =
"completed with error (electrical test element)";
break;
1861 case 0x6: msg =
"completed with error (servo/seek test element)";
break;
1862 case 0x7: msg =
"completed with error (read test element)";
break;
1863 case 0x8: msg =
"completed with error (handling damage?)";
break;
1864 default: msg =
nullptr;
1868 PrintOut(((status >> 4) >= 0x4 ? LOG_CRIT : LOG_INFO),
1869 "Device: %s, previous self-test %s\n", name, msg);
1870 else if ((status >> 4) == 0xf)
1871 PrintOut(LOG_INFO,
"Device: %s, self-test in progress, %u0%% remaining\n",
1872 name, status & 0x0f);
1874 PrintOut(LOG_INFO,
"Device: %s, unknown self-test status 0x%02x\n",
1880 unsigned char id,
const char * msg)
1885 PrintOut(LOG_INFO,
"Device: %s, can't monitor %s count - no Attribute %d\n",
1886 cfg.
name.c_str(), msg,
id);
1894 PrintOut(LOG_INFO,
"Device: %s, ignoring %s count - bogus Attribute %d value %" PRIu64
" (0x%" PRIx64
")\n",
1895 cfg.
name.c_str(), msg,
id, rawval, rawval);
1921 int set_option = 0,
bool has_value =
false)
1928 else if (set_option < 0)
1932 else if (set_option > 0)
1942 for (
const auto & prev_cfg : prev_cfgs) {
1943 if (!prev_cfg.id_is_unique)
1948 PrintOut(LOG_INFO,
"Device: %s, same identity as %s, ignored\n",
1949 cfg.
dev_name.c_str(), prev_cfg.dev_name.c_str());
1965 const char *name = cfg.
name.c_str();
1974 PrintOut(LOG_INFO,
"Device: %s, not ATA, no IDENTIFY DEVICE Structure\n",name);
1976 PrintOut(LOG_INFO,
"Device: %s, packet devices [this device %s] not SMART capable\n",
1983 char model[40+1], serial[20+1], firmware[8+1];
1993 char wwn[64]; wwn[0] = 0;
1994 unsigned oui = 0; uint64_t unique_id = 0;
1997 snprintf(wwn,
sizeof(wwn),
"WWN:%x-%06x-%09" PRIx64
", ", naa, oui, unique_id);
2018 PrintOut(LOG_INFO,
"Device: %s, smartd database not searched (Directive: -P ignore).\n", name);
2021 std::string dbversion;
2025 PrintOut(LOG_INFO,
"Device: %s, not found in smartd database%s%s.\n", name,
2026 (!dbversion.empty() ?
" " :
""), (!dbversion.empty() ? dbversion.c_str() :
""));
2028 PrintOut(LOG_INFO,
"Device: %s, found in smartd database%s%s%s%s\n",
2029 name, (!dbversion.empty() ?
" " :
""), (!dbversion.empty() ? dbversion.c_str() :
""),
2038 bool locked = ((word128 & 0x0007) == 0x0007);
2040 PrintOut(LOG_INFO,
"Device: %s, ATA Security is **LOCKED**\n", name);
2052 PrintOut(LOG_INFO,
"Device %s: presets are:\n", name);
2064 PrintOut(LOG_INFO,
"Device: %s, lacks SMART capability\n",name);
2067 PrintOut(LOG_INFO,
"Device: %s, ATA IDENTIFY DEVICE words 82-83 don't specify if SMART capable.\n",name);
2071 PrintOut(LOG_INFO,
"Device: %s, proceeding since '-T permissive' Directive given.\n",name);
2074 PrintOut(LOG_INFO,
"Device: %s, to proceed anyway, use '-T permissive' Directive.\n",name);
2082 PrintOut(LOG_INFO,
"Device: %s, could not enable SMART capability\n",name);
2086 PrintOut(LOG_INFO,
"Device: %s, to proceed anyway, use '-T permissive' Directive.\n", name);
2090 PrintOut(LOG_INFO,
"Device: %s, proceeding since '-T permissive' Directive given.\n", name);
2093 PrintOut(LOG_INFO,
"Device: %s, proceeding since SMART is already enabled\n", name);
2100 PrintOut(LOG_INFO,
"Device: %s, could not disable SMART Attribute Autosave.\n",name);
2102 PrintOut(LOG_INFO,
"Device: %s, disabled SMART Attribute Autosave.\n",name);
2108 PrintOut(LOG_INFO,
"Device: %s, could not enable SMART Attribute Autosave.\n",name);
2110 PrintOut(LOG_INFO,
"Device: %s, enabled SMART Attribute Autosave.\n",name);
2115 PrintOut(LOG_INFO,
"Device: %s, not capable of SMART Health Status check\n",name);
2126 bool smart_val_ok =
false;
2135 PrintOut(LOG_INFO,
"Device: %s, Read SMART Values failed\n", name);
2141 smart_val_ok =
true;
2143 PrintOut(LOG_INFO,
"Device: %s, Read SMART Thresholds failed%s\n",
2144 name, (cfg.
usagefailed ?
", ignoring -f Directive" :
""));
2155 "Current_Pending_Sector"))
2160 "Offline_Uncorrectable"))
2165 PrintOut(LOG_INFO,
"Device: %s, can't monitor Temperature, ignoring -W %d,%d,%d\n",
2171 for (
int id = 1;
id <= 255;
id++) {
2179 PrintOut(LOG_INFO,
"Device: %s, no Attribute %d, ignoring -%c %d%s\n", name,
id, opt,
id, excl);
2182 if (!((prefail && cfg.
prefail) || (!prefail && cfg.
usage)))
2183 PrintOut(LOG_INFO,
"Device: %s, not monitoring %s Attributes, ignoring -%c %d%s\n", name,
2184 (prefail ?
"Prefailure" :
"Usage"), opt,
id, excl);
2195 PrintOut(LOG_INFO,
"Device: %s, could not %s SMART Automatic Offline Testing.\n",name, what);
2199 PrintOut(LOG_INFO,
"Device: %s, SMART Automatic Offline Testing unsupported...\n",name);
2202 PrintOut(LOG_INFO,
"Device: %s, %s SMART Automatic Offline Testing failed.\n", name, what);
2204 PrintOut(LOG_INFO,
"Device: %s, %sd SMART Automatic Offline Testing.\n", name, what);
2210 bool smart_logdir_ok =
false, gp_logdir_ok =
false;
2216 smart_logdir_ok =
true;
2221 gp_logdir_ok =
true;
2231 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test Log, ignoring -l selftest (override with -T permissive)\n", name);
2235 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test Log, ignoring -l selftest\n", name);
2251 PrintOut(LOG_INFO,
"Device: %s, no SMART Error Log, ignoring -l error (override with -T permissive)\n", name);
2255 PrintOut(LOG_INFO,
"Device: %s, no SMART Error Log, ignoring -l error\n", name);
2266 PrintOut(LOG_INFO,
"Device: %s, no Extended Comprehensive SMART Error Log, ignoring -l xerror (override with -T permissive)\n",
2271 PrintOut(LOG_INFO,
"Device: %s, no Extended Comprehensive SMART Error Log, ignoring -l xerror\n", name);
2275 PrintOut(LOG_INFO,
"Device: %s, SMART Error Logs report different error counts: %d != %d\n",
2289 PrintOut(LOG_INFO,
"Device: %s, no SMART Offline Data Collection capability, ignoring -l offlinests (override with -T permissive)\n", name);
2291 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test capability, ignoring -l selfteststs (override with -T permissive)\n", name);
2300 if (-1 == powermode) {
2301 PrintOut(LOG_CRIT,
"Device: %s, no ATA CHECK POWER STATUS support, ignoring -n Directive\n", name);
2304 else if (powermode!=0x00 && powermode!=0x01
2305 && powermode!=0x40 && powermode!=0x41
2306 && powermode!=0x80 && powermode!=0x81 && powermode!=0x82 && powermode!=0x83
2307 && powermode!=0xff) {
2308 PrintOut(LOG_CRIT,
"Device: %s, CHECK POWER STATUS returned %d, not ATA compliant, ignoring -n Directive\n",
2350 PrintOut(LOG_INFO,
"Device: %s, ATA settings applied: %s\n", name, msg.c_str());
2355 PrintOut(LOG_INFO,
"Device: %s, no SCT Error Recovery Control support, ignoring -l scterc\n",
2358 PrintOut(LOG_INFO,
"Device: %s, no SCT support if ATA Security is LOCKED, ignoring -l scterc\n",
2362 PrintOut(LOG_INFO,
"Device: %s, set of SCT Error Recovery Control failed\n", name);
2364 PrintOut(LOG_INFO,
"Device: %s, SCT Error Recovery Control set to: Read: %u, Write: %u\n",
2379 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n",name);
2392 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", name, cfg.
state_file.c_str());
2411 int err, req_len, avail_len, version, len;
2412 const char *device = cfg.
name.c_str();
2416 uint8_t vpdBuf[252];
2417 char lu_id[64], serial[256], vendor[40], model[40];
2420 memset(inqBuf, 0, 96);
2427 PrintOut(LOG_INFO,
"Device: %s, Both 36 and 64 byte INQUIRY failed; "
2428 "skip device [err=%d, %d]\n", device, err, err64);
2432 version = (inqBuf[2] & 0x7f);
2434 avail_len = inqBuf[4] + 5;
2435 len = (avail_len < req_len) ? avail_len : req_len;
2437 PrintOut(LOG_INFO,
"Device: %s, INQUIRY response less than 36 bytes; "
2438 "skip device\n", device);
2442 int pdt = inqBuf[0] & 0x1f;
2453 PrintOut(LOG_INFO,
"Device: %s, not a disk like device [PDT=0x%x], "
2454 "skip\n", device, pdt);
2465 if (version >= 0x3) {
2468 vpdBuf,
sizeof(vpdBuf))) {
2475 vpdBuf,
sizeof(vpdBuf))) {
2477 vpdBuf[4 + len] =
'\0';
2492 (
char *)&inqBuf[8], (
char *)&inqBuf[16], (
char *)&inqBuf[32],
2493 (lu_id[0] ?
", lu id: " :
""), (lu_id[0] ? lu_id :
""),
2494 (serial[0] ?
", S/N: " :
""), (serial[0] ? serial :
""),
2495 (si_str[0] ?
", " :
""), (si_str[0] ? si_str :
""));
2515 PrintOut(LOG_INFO,
"Device: %s, NOT READY (e.g. spun down); skip device\n", device);
2517 PrintOut(LOG_INFO,
"Device: %s, NO MEDIUM present; skip device\n", device);
2519 PrintOut(LOG_INFO,
"Device: %s, BECOMING (but not yet) READY; skip device\n", device);
2521 PrintOut(LOG_CRIT,
"Device: %s, failed Test Unit Ready [err=%d]\n", device, err);
2538 "Device: %s, Bad IEC (SMART) mode page, err=%d, skip device\n",
2547 PrintOut(LOG_INFO,
"Device: %s, IE (SMART) not enabled, skip device\n"
2548 "Try 'smartctl -s on %s' to turn on SMART features\n",
2590 uint8_t currenttemp = 0;
2591 uint8_t triptemp = 0;
2594 &asc, &ascq, ¤ttemp, &triptemp)) {
2595 PrintOut(LOG_INFO,
"Device: %s, unexpectedly failed to read SMART values\n", device);
2600 PrintOut(LOG_INFO,
"Device: %s, can't monitor Temperature, ignoring -W %d,%d,%d\n",
2611 PrintOut(LOG_INFO,
"Device: %s, does not support SMART Self-Test Log.\n", device);
2626 PrintOut(LOG_INFO,
"Device: %s, could not disable autosave (set GLTSD bit).\n",device);
2628 PrintOut(LOG_INFO,
"Device: %s, disabled autosave (set GLTSD bit).\n",device);
2634 PrintOut(LOG_INFO,
"Device: %s, could not enable autosave (clear GLTSD bit).\n",device);
2636 PrintOut(LOG_INFO,
"Device: %s, enabled autosave (cleared GLTSD bit).\n",device);
2640 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n", device);
2656 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", device, cfg.
state_file.c_str());
2673 for (
int i = 8; i < 16; i++) {
2675 return ~(uint64_t)0;
2677 uint64_t lo = val[7];
2678 for (
int i = 7-1; i >= 0; i--) {
2679 lo <<= 8; lo += val[i];
2697 uint64_t newcnt = 0)
2701 unsigned want_entries = 64;
2708 if (!read_entries) {
2709 PrintOut(LOG_INFO,
"Device: %s, Read %u entries from Error Information Log failed\n",
2710 cfg.
name.c_str(), want_entries);
2719 int err = 0, ign = 0;
2720 for (
unsigned i = 0; i < read_entries; i++) {
2740 PrintOut(LOG_INFO,
"Device: %s, NVMe error [%u], count %" PRIu64
", status 0x%04x: %s\n",
2745 std::string msg =
strprintf(
"Device: %s, NVMe error count increased from %" PRIu64
" to %" PRIu64
2746 " (%d new, %d ignored, %" PRIu64
" unknown)",
2747 cfg.
name.c_str(), oldcnt, newcnt, err, ign,
2748 (mincnt > oldcnt + 1 ? mincnt - oldcnt - 1 : 0));
2751 PrintOut(LOG_INFO,
"%s\n", msg.c_str());
2754 PrintOut(LOG_CRIT,
"%s\n", msg.c_str());
2766 const char *name = cfg.
name.c_str();
2773 PrintOut(LOG_INFO,
"Device: %s, NVMe Identify Controller failed\n", name);
2779 char model[40+1], serial[20+1], firmware[8+1];
2785 char nsstr[32] =
"", capstr[32] =
"";
2788 snprintf(nsstr,
sizeof(nsstr),
", NSID:%u",
nsid);
2793 nsstr, (capstr[0] ?
", " :
""), capstr);
2810 PrintOut(LOG_INFO,
"Device: %s, failed to read NVMe SMART/Health Information\n", name);
2818 PrintOut(LOG_INFO,
"Device: %s, no Temperature sensors, ignoring -W %d,%d,%d\n",
2828 PrintOut(LOG_INFO,
"Device: %s, Error Information unavailable, ignoring -l [x]error\n", name);
2843 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n", name);
2856 snprintf(nsstr,
sizeof(nsstr),
"-n%u",
nsid);
2860 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", name, cfg.
state_file.c_str());
2872 const char * name = cfg.
name.c_str();
2876 MailWarning(cfg, state, 0,
"TEST EMAIL from smartd for device: %s", name);
2891 PrintOut(LOG_INFO,
"Device: %s, is in %s mode, suspending checks\n", name,
"STANDBY (OS)");
2902 if (!device->
open()) {
2905 PrintOut(LOG_INFO,
"Device: %s, open() of %s device failed: %s\n", name, type, device->
get_errmsg());
2906 MailWarning(cfg, state, 9,
"Device: %s, unable to open %s device", name, type);
2909 PrintOut(LOG_INFO,
"Device: %s, removed %s device: %s\n", name, type, device->
get_errmsg());
2913 PrintOut(LOG_INFO,
"Device: %s, %s device still removed: %s\n", name, type, device->
get_errmsg());
2918 PrintOut(LOG_INFO,
"Device: %s, opened %s device\n", name, type);
2923 PrintOut(LOG_INFO,
"Device: %s, reconnected %s device\n", name, type);
2934 const char * name = cfg.
name.c_str();
2938 MailWarning(cfg, state, 8,
"Device: %s, Read SMART Self-Test Log Failed", name);
2952 PrintOut(LOG_CRIT,
"Device: %s, Self-Test Log error count increased from %d to %d\n",
2954 MailWarning(cfg, state, 3,
"Device: %s, Self-Test Log error count increased from %d to %d",
2958 else if (newc > 0 && oldh != newh) {
2966 PrintOut(LOG_CRIT,
"Device: %s, new Self-Test Log error at hour timestamp %d\n",
2968 MailWarning(cfg, state, 3,
"Device: %s, new Self-Test Log error at hour timestamp %d",
2976 PrintOut(LOG_INFO,
"Device: %s, Self-Test Log error count decreased from %d to %d\n",
3013 time_t now = (!usetime ? time(
nullptr) : usetime);
3027 unsigned offsets[max_offsets] = {0, }, limits[max_offsets] = {0, };
3028 unsigned num_offsets = 1;
3030 const char * q = strchr(p,
':');
3034 unsigned offset = 0, limit = 0;
int n1 = -1, n2 = -1, n3 = -1;
3035 sscanf(p,
"%u%n-%n%u%n", &offset, &n1, &n2, &limit, &n3);
3036 if (!(n1 == 3 && (n2 < 0 || (n3 == 3+1+3 && limit > 0))))
3038 offsets[num_offsets] = offset; limits[num_offsets] = limit;
3040 p += (n3 > 0 ? n3 : n1);
3045 time_t testtime = 0;
int testhour = 0;
3050 for (
unsigned i = 0; i < num_offsets; i++) {
3051 unsigned offset = offsets[i], limit = limits[i];
3053 if (0 < limit && limit < delay)
3058 int weekday = (tms->tm_wday ? tms->tm_wday : 7);
3059 for (
int j = 0; j <= maxtest; j++) {
3072 snprintf(pattern,
sizeof(pattern),
"%c/%02d/%02d/%1d/%02d",
3073 test_type_chars[j], tms->tm_mon+1, tms->tm_mday, weekday, tms->tm_hour);
3075 const unsigned len =
sizeof(
"S/01/01/1/01") - 1;
3076 snprintf(pattern + len,
sizeof(pattern) - len,
":%03u", offset);
3078 snprintf(pattern + len + 4,
sizeof(pattern) - len - 4,
"-%03u", limit);
3082 testtype = pattern[0];
3083 testtime = t; testhour = tms->tm_hour;
3097 if ((t += 3600) > now)
3108 if (!usetime && !(testhour == tmnow->tm_hour && testtime + 3600 > now)) {
3110 PrintOut(LOG_INFO,
"Device: %s, old test of type %c not run at %s, starting now.\n",
3111 cfg.
name.c_str(), testtype, datebuf);
3121 unsigned numdev = configs.size();
3126 PrintOut(LOG_INFO,
"\nNext scheduled self tests (at most 5 of each type per device):\n");
3129 time_t now = time(
nullptr);
3136 time_t testtime = now + seconds;
3137 for (
unsigned i = 0; i < numdev; i++) {
3147 PrintOut(LOG_INFO,
"Device: %s, will do test %d of type %c at %s\n", cfg.
name.c_str(),
3156 PrintOut(LOG_INFO,
"\nTotals [%s - %s]:\n", datenow, date);
3157 for (
unsigned i = 0; i < numdev; i++) {
3159 bool scsi =
devices.at(i)->is_scsi();
3164 PrintOut(LOG_INFO,
"Device: %s, will do %3d test%s of type %c\n", cfg.
name.c_str(),
3176 const char *testname =
nullptr;
3177 const char *name = cfg.
name.c_str();
3181 PrintOut(LOG_CRIT,
"Device: %s, does not support Self-Tests\n", name);
3186 if (1 == inProgress) {
3187 PrintOut(LOG_INFO,
"Device: %s, skip since Self-Test already in "
3188 "progress.\n", name);
3194 testname =
"Short Self";
3198 testname =
"Long Self";
3204 PrintOut(LOG_CRIT,
"Device: %s, not capable of %c Self-Test\n", name,
3211 PrintOut(LOG_CRIT,
"Device: %s, not capable of %s-Test\n", name,
3220 PrintOut(LOG_CRIT,
"Device: %s, execute %s-Test failed (err: %d)\n", name,
3225 PrintOut(LOG_INFO,
"Device: %s, starting scheduled %s-Test.\n", name, testname);
3234 const char *name = cfg.
name.c_str();
3239 PrintOut(LOG_CRIT,
"Device: %s, not capable of Offline or Self-Testing.\n", name);
3244 int dotest = -1, mode = 0;
3245 const char *testname =
nullptr;
3248 testname=
"Offline Immediate ";
3255 testname=
"Conveyance Self-";
3262 testname=
"Short Self-";
3269 testname=
"Long Self-";
3276 case 'c':
case 'n':
case 'r':
3277 testname =
"Selective Self-";
3293 PrintOut(LOG_CRIT,
"Device: %s, not capable of %sTest\n", name, testname);
3298 if (15==(
data.self_test_exec_status >> 4)) {
3300 PrintOut(LOG_INFO,
"Device: %s, will not skip scheduled %sTest "
3301 "despite unclear Self-Test byte (SAMSUNG Firmware bug).\n", name, testname);
3303 PrintOut(LOG_INFO,
"Device: %s, skip scheduled %sTest; %1d0%% remaining of current Self-Test.\n",
3304 name, testname, (
int)(
data.self_test_exec_status & 0x0f));
3318 PrintOut(LOG_CRIT,
"Device: %s, prepare %sTest failed\n", name, testname);
3322 PrintOut(LOG_INFO,
"Device: %s, %s test span at LBA %" PRIu64
" - %" PRIu64
" (%" PRIu64
" sectors, %u%% - %u%% of disk).\n",
3324 start, end, end - start + 1,
3334 PrintOut(LOG_CRIT,
"Device: %s, execute %sTest failed.\n", name, testname);
3340 if (testtype ==
'O')
3345 PrintOut(LOG_INFO,
"Device: %s, starting scheduled %sTest.\n", name, testname);
3351 unsigned char id,
bool increase_only,
3353 int mailtype,
const char * msg)
3369 if (!(!increase_only || prev_rawval < rawval))
3373 std::string
s =
strprintf(
"Device: %s, %" PRId64
" %s", cfg.
name.c_str(), rawval, msg);
3374 if (prev_rawval > 0 && rawval != prev_rawval)
3375 s +=
strprintf(
" (changed %+" PRId64
")", rawval - prev_rawval);
3383static const char *
fmt_temp(
unsigned char x,
char (& buf)[20])
3387 snprintf(buf,
sizeof(buf),
"%u", x);
3394 if (!(0 < currtemp && currtemp < 255)) {
3395 PrintOut(LOG_INFO,
"Device: %s, failed to read Temperature\n", cfg.
name.c_str());
3400 const char * minchg =
"", * maxchg =
"";
3401 if (currtemp > state.
tempmax) {
3414 PrintOut(LOG_INFO,
"Device: %s, initial Temperature is %d Celsius (Min/Max %s/%u%s)\n",
3417 PrintOut(LOG_INFO,
" [trip Temperature is %d Celsius]\n", (
int)triptemp);
3441 PrintOut(LOG_INFO,
"Device: %s, Temperature changed %+d Celsius to %u Celsius (Min/Max %s%s/%u%s)\n",
3449 PrintOut(LOG_CRIT,
"Device: %s, Temperature %u Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)\n",
3451 MailWarning(cfg, state, 12,
"Device: %s, Temperature %d Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)",
3455 PrintOut(LOG_INFO,
"Device: %s, Temperature %u Celsius reached limit of %u Celsius (Min/Max %s%s/%u%s)\n",
3460 if (currtemp < limit)
3461 reset_warning_mail(cfg, state, 12,
"Temperature %u Celsius dropped below %u Celsius", currtemp, limit);
3481 PrintOut(LOG_CRIT,
"Device: %s, Failed SMART usage Attribute: %d %s.\n", cfg.
name.c_str(), attr.
id, attrname.c_str());
3482 MailWarning(cfg, state, 2,
"Device: %s, Failed SMART usage Attribute: %d %s.", cfg.
name.c_str(), attr.
id, attrname.c_str());
3488 if (!( ( prefail && cfg.
prefail)
3489 || (!prefail && cfg.
usage )))
3497 if (attr.
id != prev.
id) {
3498 PrintOut(LOG_INFO,
"Device: %s, same Attribute has different ID numbers: %d = %d\n",
3499 cfg.
name.c_str(), attr.
id, prev.
id);
3504 bool valchanged =
false;
3511 bool rawchanged =
false;
3519 if (!(valchanged || rawchanged))
3523 std::string currstr, prevstr;
3545 std::string msg =
strprintf(
"Device: %s, SMART %s Attribute: %d %s changed from %s to %s",
3546 cfg.
name.c_str(), (prefail ?
"Prefailure" :
"Usage"), attr.
id,
3548 prevstr.c_str(), currstr.c_str());
3553 PrintOut(LOG_CRIT,
"%s\n", msg.c_str());
3557 PrintOut(LOG_INFO,
"%s\n", msg.c_str());
3564 bool firstpass,
bool allow_selftests)
3569 const char * name = cfg.
name.c_str();
3576 const char * mode = 0;
3577 if (0 <= powermode && powermode < 0xff) {
3582 if (powermode2 > powermode)
3583 PrintOut(LOG_INFO,
"Device: %s, CHECK POWER STATUS spins up disk (0x%02x -> 0x%02x)\n", name, powermode, powermode2);
3584 powermode = powermode2;
3636 mode=
"ACTIVE or IDLE";
3640 PrintOut(LOG_CRIT,
"Device: %s, CHECK POWER STATUS returned %d, not ATA compliant, ignoring -n Directive\n",
3653 PrintOut(LOG_INFO,
"Device: %s, is in %s mode, suspending checks\n", name, mode);
3660 PrintOut(LOG_INFO,
"Device: %s, %s mode ignored due to reached limit of skipped checks (%d check%s skipped)\n",
3667 PrintOut(LOG_INFO,
"Device: %s, is back in %s mode, resuming checks (%d check%s skipped)\n",
3678 PrintOut(LOG_INFO,
"Device: %s, not capable of SMART self-check\n",name);
3679 MailWarning(cfg, state, 5,
"Device: %s, not capable of SMART self-check", name);
3682 else if (status==1){
3683 PrintOut(LOG_CRIT,
"Device: %s, FAILED SMART self-check. BACK UP DATA NOW!\n", name);
3684 MailWarning(cfg, state, 1,
"Device: %s, FAILED SMART self-check. BACK UP DATA NOW!", name);
3698 PrintOut(LOG_CRIT,
"Device: %s, failed to read SMART Attribute Data\n", name);
3699 MailWarning(cfg, state, 6,
"Device: %s, failed to read SMART Attribute Data", name);
3709 :
"Total unreadable (pending) sectors" ));
3714 :
"Total offline uncorrectable sectors"));
3762 int errcnt1 = -1, errcnt2 = -1;
3769 int newc = (errcnt1 >= errcnt2 ? errcnt1 : errcnt2);
3774 MailWarning(cfg, state, 7,
"Device: %s, Read SMART Error Log Failed", name);
3779 PrintOut(LOG_CRIT,
"Device: %s, ATA error count increased from %d to %d\n",
3781 MailWarning(cfg, state, 4,
"Device: %s, ATA error count increased from %d to %d",
3809 const char * name = cfg.
name.c_str();
3811 uint8_t asc = 0, ascq = 0;
3812 uint8_t currenttemp = 0, triptemp = 0;
3815 &asc, &ascq, ¤ttemp, &triptemp)) {
3816 PrintOut(LOG_INFO,
"Device: %s, failed to read SMART values\n",
3818 MailWarning(cfg, state, 6,
"Device: %s, failed to read SMART values", name);
3827 PrintOut(LOG_CRIT,
"Device: %s, SMART Failure: %s\n", name, cp);
3828 MailWarning(cfg, state, 1,
"Device: %s, SMART Failure: %s", name, cp);
3829 }
else if (asc == 4 && ascq == 9) {
3830 PrintOut(LOG_INFO,
"Device: %s, self-test in progress\n", name);
3832 PrintOut(LOG_INFO,
"Device: %s, non-SMART asc,ascq: %d,%d\n",
3833 name, (
int)asc, (
int)ascq);
3835 PrintOut(LOG_INFO,
"Device: %s, SMART health: passed\n", name);
3891 const char * name = cfg.
name.c_str();
3898 PrintOut(LOG_INFO,
"Device: %s, failed to read NVMe SMART/Health Information\n", name);
3899 MailWarning(cfg, state, 6,
"Device: %s, failed to read NVMe SMART/Health Information", name);
3908 static const char *
const wnames[] =
3909 {
"LowSpare",
"Temperature",
"Reliability",
"R/O",
"VolMemBackup"};
3911 for (
unsigned b = 0, cnt = 0;
b < 8 ;
b++) {
3912 if (!(
w & (1 <<
b)))
3917 msg +=
"...";
break;
3919 if (
b >=
sizeof(wnames)/
sizeof(wnames[0])) {
3920 msg +=
"*Unknown*";
break;
3925 PrintOut(LOG_CRIT,
"Device: %s, Critical Warning (0x%02x): %s\n", name,
w, msg.c_str());
3926 MailWarning(cfg, state, 1,
"Device: %s, Critical Warning (0x%02x): %s", name,
w, msg.c_str());
3963 bool sts1 =
false, sts2 =
false;
3964 for (
const auto & cfg : configs) {
3965 if (cfg.offlinests_ns)
3967 if (cfg.selfteststs_ns)
3974 if (!
smi()->disable_system_auto_standby(
false)) {
3976 PrintOut(LOG_CRIT,
"System auto standby enable failed: %s\n",
smi()->get_errmsg());
3978 PrintOut(LOG_INFO,
"Disable auto standby not supported, ignoring ',ns' from %s%s%s\n",
3979 (sts1 ?
"-l offlinests,ns" :
""), (sts1 && sts2 ?
" and " :
""), (sts2 ?
"-l selfteststs,ns" :
""));
3980 sts1 = sts2 =
false;
3994 bool running =
false;
3995 for (
unsigned i = 0; i < configs.size() && !running; i++) {
4011 if (!
smi()->disable_system_auto_standby(
false))
4012 PrintOut(LOG_CRIT,
"Self-test(s) completed, system auto standby enable failed: %s\n",
4013 smi()->get_errmsg());
4015 PrintOut(LOG_INFO,
"Self-test(s) completed, system auto standby enabled\n");
4019 else if (!
smi()->disable_system_auto_standby(
true)) {
4021 PrintOut(LOG_INFO,
"Self-test(s) in progress, system auto standby disable rejected: %s\n",
4022 smi()->get_errmsg());
4028 PrintOut(LOG_INFO,
"Self-test(s) in progress, system auto standby disabled\n");
4038 for (
unsigned i = 0; i < configs.size(); i++) {
4043 PrintOut(LOG_INFO,
"Device: %s, skipped (interval=%d)\n", cfg.
name.c_str(),
4084static void ToggleDebugMode()
4087 PrintOut(LOG_INFO,
"Signal USR2 - enabling debug mode\n");
4088 if (!daemon_enable_console(
"smartd [Debug]")) {
4091 PrintOut(LOG_INFO,
"smartd debug mode enabled, PID=%d\n", getpid());
4094 PrintOut(LOG_INFO,
"enable console failed\n");
4097 daemon_disable_console();
4100 PrintOut(LOG_INFO,
"Signal USR2 - debug mode disabled\n");
4109 if (timenow < wakeuptime)
4111 return timenow + ct - (timenow - wakeuptime) % ct;
4118 time_t timenow = time(
nullptr);
4119 unsigned n = configs.size();
4129 for (
unsigned i = 0; i < n; i++) {
4135 if (!wakeuptime || state.
wakeuptime < wakeuptime)
4144 bool no_skip =
false;
4148 if (wakeuptime > timenow + ct) {
4149 PrintOut(LOG_INFO,
"System clock time adjusted to the past. Resetting next wakeup time.\n");
4150 wakeuptime = timenow + ct;
4151 for (
auto & state : states)
4152 state.wakeuptime = 0;
4157 sleep(wakeuptime+addtime-timenow);
4161 if (caughtsigUSR2) {
4167 timenow = time(
nullptr);
4170 if (!addtime && timenow > wakeuptime+60) {
4172 PrintOut(LOG_INFO,
"Sleep time was %d seconds too long, assuming wakeup from standby mode.\n",
4173 (
int)(timenow-wakeuptime));
4175 addtime = timenow-wakeuptime+20;
4177 int nextcheck = ct - addtime % ct;
4178 if (nextcheck <= 20)
4179 addtime += nextcheck;
4185 PrintOut(LOG_INFO,
"Signal USR1 - checking devices now rather than in %d seconds.\n",
4186 wakeuptime-timenow>0?(
int)(wakeuptime-timenow):0);
4188 sigwakeup = no_skip =
true;
4193 for (
auto & state : states)
4194 state.skip = (!no_skip && timenow < state.wakeuptime);
4206 PrintOut(priority,
"never[,N][,q], sleep[,N][,q], standby[,N][,q], idle[,N][,q]");
4209 PrintOut(priority,
"valid_regular_expression");
4212 PrintOut(priority,
"%s",
smi()->get_valid_dev_types_str().c_str());
4215 PrintOut(priority,
"normal, permissive");
4222 PrintOut(priority,
"error, selftest");
4225 PrintOut(priority,
"\"once\", \"always\", \"daily\", \"diminishing\", \"test\", \"exec\"");
4231 PrintOut(priority,
"use, ignore, show, showall");
4237 PrintOut(priority,
"aam,[N|off], apm,[N|off], lookahead,[on|off], dsn,[on|off] "
4238 "security-freeze, standby,[N|off], wcache,[on|off]");
4241 PrintOut(priority,
"i=N, interval=N");
4247static int GetInteger(
const char *arg,
const char *name,
const char *token,
int lineno,
const char *cfgfile,
4248 int min,
int max,
char * suffix = 0)
4252 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s takes integer argument from %d to %d.\n",
4253 cfgfile, lineno, name, token, min, max);
4259 int val = strtol(arg,&endptr,10);
4263 if (!strcmp(endptr, suffix))
4264 endptr += strlen(suffix);
4269 if (!(!*endptr && min <= val && val <= max)) {
4270 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s has argument: %s; needs integer from %d to %d.\n",
4271 cfgfile, lineno, name, token, arg, min, max);
4281static int Get3Integers(
const char *arg,
const char *name,
const char *token,
int lineno,
const char *cfgfile,
4282 unsigned char *val1,
unsigned char *val2,
unsigned char *val3)
4284 unsigned v1 = 0, v2 = 0, v3 = 0;
4285 int n1 = -1, n2 = -1, n3 = -1, len;
4287 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s takes 1-3 integer argument(s) from 0 to 255.\n",
4288 cfgfile, lineno, name, token);
4293 if (!( sscanf(arg,
"%u%n,%u%n,%u%n", &v1, &n1, &v2, &n2, &v3, &n3) >= 1
4294 && (n1 == len || n2 == len || n3 == len) && v1 <= 255 && v2 <= 255 && v3 <= 255)) {
4295 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s has argument: %s; needs 1-3 integer(s) from 0 to 255.\n",
4296 cfgfile, lineno, name, token, arg);
4299 *val1 = (
unsigned char)v1; *val2 = (
unsigned char)v2; *val3 = (
unsigned char)v3;
4307static const char * strtok_dequote(
const char * delimiters)
4309 const char * t = strtok(
nullptr, delimiters);
4310 if (!t || t[0] !=
'"')
4313 static std::string token;
4316 t = strtok(
nullptr, delimiters);
4320 int len = strlen(t);
4321 if (t[len-1] ==
'"') {
4322 token += std::string(t, len-1);
4327 return token.c_str();
4339 const char * name = cfg.
name.c_str();
4341 const char *delim =
" \n\t";
4344 const char *arg = 0;
4351 if (*token!=
'-' || strlen(token)!=2) {
4352 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): unknown Directive: %s\n",
4354 PrintOut(LOG_CRIT,
"Run smartd -D to print a list of valid Directives.\n");
4363 char plus[] =
"+", excl[] =
"!";
4368 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 0, 255, plus)) < 0)
4376 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 0, 255, plus)) < 0)
4384 if (!(arg = strtok(
nullptr, delim))) {
4386 }
else if (!strcmp(arg,
"normal")) {
4391 }
else if (!strcmp(arg,
"permissive")) {
4400 if (!(arg = strtok(
nullptr, delim))) {
4402 }
else if (!strcmp(arg,
"ignore")) {
4404 }
else if (!strcmp(arg,
"removable")) {
4406 }
else if (!strcmp(arg,
"auto")) {
4411 scan_types.push_back(arg);
4416 if (!(arg = strtok(
nullptr, delim)))
4444 if (!(arg = strtok(
nullptr, delim))) {
4446 }
else if (!strcmp(arg,
"selftest")) {
4449 }
else if (!strcmp(arg,
"error")) {
4452 }
else if (!strcmp(arg,
"xerror")) {
4455 }
else if (!strcmp(arg,
"offlinests")) {
4458 }
else if (!strcmp(arg,
"offlinests,ns")) {
4461 }
else if (!strcmp(arg,
"selfteststs")) {
4464 }
else if (!strcmp(arg,
"selfteststs,ns")) {
4467 }
else if (!strncmp(arg,
"scterc,",
sizeof(
"scterc,")-1)) {
4469 unsigned rt = ~0, wt = ~0;
int nc = -1;
4470 sscanf(arg,
"scterc,%u,%u%n", &rt, &wt, &nc);
4471 if (nc == (
int)strlen(arg) && rt <= 999 && wt <= 999) {
4494 if (!(arg = strtok(
nullptr, delim))) {
4496 }
else if (!strcmp(arg,
"on")) {
4498 }
else if (!strcmp(arg,
"off")) {
4506 if (!(arg = strtok(
nullptr, delim)))
4509 char *endptr =
nullptr;
4510 char *next = strchr(
const_cast<char*
>(arg),
',');
4517 if (!strcmp(arg,
"never"))
4519 else if (!strcmp(arg,
"sleep"))
4521 else if (!strcmp(arg,
"standby"))
4523 else if (!strcmp(arg,
"idle"))
4529 if (!badarg && next) {
4535 next = endptr + (*endptr !=
'\0');
4539 if (*next !=
'\0') {
4540 if (!strcmp(
"q", next))
4551 if (!(arg = strtok(
nullptr, delim))) {
4553 }
else if (!strcmp(arg,
"on")) {
4555 }
else if (!strcmp(arg,
"off")) {
4564 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous Test Directive -s %s\n",
4569 if (!(arg = strtok(
nullptr, delim))) {
4576 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): -s argument \"%s\" is INVALID extended regular expression. %s.\n",
4585 "[^]$()*+./:?^[|0-9LSCOncr-]+|"
4586 ":[0-9]{0,2}($|[^0-9])|:[0-9]{4,}|"
4587 ":[0-9]{3}-(000|[0-9]{0,2}($|[^0-9])|[0-9]{4,})"
4590 if (syntax_check.
execute(arg, 1, &range) && 0 <= range.rm_so && range.rm_so < range.rm_eo)
4591 PrintOut(LOG_INFO,
"File %s line %d (drive %s): warning, \"%.*s\" looks odd in "
4592 "extended regular expression \"%s\"\n",
4593 configfile, lineno, name, (
int)(range.rm_eo - range.rm_so), arg + range.rm_so, arg);
4598 if (!(arg = strtok(
nullptr, delim)))
4602 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous Address Directive -m %s\n",
4609 if (!(arg = strtok(
nullptr, delim)))
4611 else if (!strcmp(arg,
"once"))
4613 else if (!strcmp(arg,
"always"))
4615 else if (!strcmp(arg,
"daily"))
4617 else if (!strcmp(arg,
"diminishing"))
4619 else if (!strcmp(arg,
"test"))
4621 else if (!strcmp(arg,
"exec")) {
4625 arg = strtok_dequote(delim);
4626 if (arg && arg[0] ==
'"') {
4627 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive %s 'exec' argument: missing closing quote\n",
4632 arg = strtok(
nullptr, delim);
4635 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive %s 'exec' argument must be followed by executable path.\n",
4641 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous mail Directive -M exec %s\n",
4650 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255)) < 0)
4656 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255)) < 0)
4662 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255, excl)) < 0)
4670 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255, excl)) < 0)
4684 if (!(arg = strtok(
nullptr, delim))) {
4692 if (!(arg = strtok(
nullptr, delim))) {
4694 }
else if (!strcmp(arg,
"use")) {
4696 }
else if (!strcmp(arg,
"ignore")) {
4698 }
else if (!strcmp(arg,
"show")) {
4700 }
else if (!strcmp(arg,
"showall")) {
4709 if (!(arg = strtok(
nullptr, delim))) {
4713 char arg2[16+1];
unsigned uval;
4714 int n1 = -1, n2 = -1, n3 = -1, len = strlen(arg);
4715 if (sscanf(arg,
"%16[^,=]%n%*[,=]%n%u%n", arg2, &n1, &n2, &uval, &n3) >= 1
4716 && (n1 == len || n2 > 0)) {
4717 bool on = (n2 > 0 && !strcmp(arg+n2,
"on"));
4718 bool off = (n2 > 0 && !strcmp(arg+n2,
"off"));
4722 if (!strcmp(arg2,
"aam")) {
4725 else if (uval <= 254)
4730 else if (!strcmp(arg2,
"apm")) {
4733 else if (1 <= uval && uval <= 254)
4738 else if (!strcmp(arg2,
"lookahead")) {
4746 else if (!strcmp(arg,
"security-freeze")) {
4749 else if (!strcmp(arg2,
"standby")) {
4752 else if (uval <= 255)
4757 else if (!strcmp(arg2,
"wcache")) {
4765 else if (!strcmp(arg2,
"dsn")) {
4784 if (!(arg = strtok(
nullptr, delim))) {
4788 int n = 0, nc = -1, len = strlen(arg);
4789 if ( ( sscanf(arg,
"i=%d%n", &n, &nc) == 1
4790 || sscanf(arg,
"interval=%d%n", &n, &nc) == 1)
4791 && nc == len && n >= 10)
4800 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): unknown Directive: %s\n",
4802 PrintOut(LOG_CRIT,
"Run smartd -D to print a list of valid Directives.\n");
4806 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Missing argument to %s Directive\n",
4810 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Invalid argument to %s Directive: %s\n",
4813 if (missingarg || badarg) {
4814 PrintOut(LOG_CRIT,
"Valid arguments to %s Directive are: ", token);
4824#define SCANDIRECTIVE "DEVICESCAN"
4838 const char *delim =
" \n\t";
4841 const char * name = strtok(line, delim);
4842 if (!name || *name ==
'#')
4847 if (!strcmp(
"DEFAULT", name)) {
4855 conf_entries.push_back(default_conf);
4857 dev_config & cfg = (retval ? conf_entries.back() : default_conf);
4864 while (
char * token = strtok(
nullptr, delim)) {
4878 if (retval != -1 && scan_types.size() > 1) {
4879 PrintOut(LOG_CRIT,
"Drive: %s, invalid multiple -d TYPE Directives on line %d of file %s\n",
4895 PrintOut(LOG_INFO,
"Drive: %s, implied '-a' Directive on line %d of file %s\n",
4910 PrintOut(LOG_CRIT,
"Drive: %s, -M Directive(s) on line %d of file %s need -m ADDRESS Directive\n",
4919 PrintOut(LOG_CRIT,
"Drive: %s, -m <nomailer> Directive on line %d of file %s needs -M exec Directive\n",
4944 const int MAXLINELEN = 256;
4946 const int MAXCONTLINE = 1023;
4953 int ret = (errno!=ENOENT ? -3 : -2);
4954 PrintOut(LOG_CRIT,
"%s: Unable to open configuration file %s\n",
4970 if (
ParseConfigLine(conf_entries, default_conf, scan_types, 0, fakeconfig) != -1)
4971 throw std::logic_error(
"Internal error parsing " SCANDIRECTIVE);
4976 setmode(fileno(f), O_TEXT);
4983 int lineno = 1, cont = 0, contlineno = 0;
4984 char line[MAXLINELEN+2];
4985 char fullline[MAXCONTLINE+1];
4988 int len=0,scandevice;