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;
332 if (getenv(
"NOTIFY_SOCKET")) {
333 PrintOut(LOG_CRIT,
"This version of smartd was build without 'Type=notify' support.\n");
369 bool is_set(
int id,
unsigned char flag)
const
370 {
return (0 <
id &&
id < (
int)
sizeof(
m_flags) && (
m_flags[
id] & flag)); }
374 if (0 <
id &&
id < (
int)
sizeof(
m_flags))
587 | ((uint64_t)ta.
raw[3] << 24)
588 | ((uint64_t)ta.
raw[4] << 32)
589 | ((uint64_t)ta.
raw[5] << 40);
603 memset(ta.
raw, 0,
sizeof(ta.
raw));
608 ta.
raw[0] = (
unsigned char) pa.
raw;
609 ta.
raw[1] = (
unsigned char)(pa.
raw >> 8);
610 ta.
raw[2] = (
unsigned char)(pa.
raw >> 16);
611 ta.
raw[3] = (
unsigned char)(pa.
raw >> 24);
612 ta.
raw[4] = (
unsigned char)(pa.
raw >> 32);
613 ta.
raw[5] = (
unsigned char)(pa.
raw >> 40);
625 "|(self-test-errors)"
626 "|(self-test-last-err-hour)"
627 "|(scheduled-test-next-check)"
628 "|(selective-test-last-start)"
629 "|(selective-test-last-end)"
631 "|(mail\\.([0-9]+)\\."
637 "|(ata-smart-attribute\\.([0-9]+)\\."
645 "|(nvme-err-log-entries)"
647 " *= *([0-9]+)[ \n]*$"
650 const int nmatch = 1+25;
654 if (
match[nmatch-1].rm_so < 0)
657 uint64_t val = strtoull(line +
match[nmatch-1].rm_so, (
char **)0, 10);
660 if (
match[++m].rm_so >= 0)
661 state.
tempmin = (
unsigned char)val;
662 else if (
match[++m].rm_so >= 0)
663 state.
tempmax = (
unsigned char)val;
664 else if (
match[++m].rm_so >= 0)
666 else if (
match[++m].rm_so >= 0)
668 else if (
match[++m].rm_so >= 0)
670 else if (
match[++m].rm_so >= 0)
672 else if (
match[++m].rm_so >= 0)
674 else if (
match[++m].rm_so >= 0)
676 else if (
match[m+=2].rm_so >= 0) {
677 int i = atoi(line+
match[m].rm_so);
682 if (
match[m+=2].rm_so >= 0)
684 else if (
match[++m].rm_so >= 0)
686 else if (
match[++m].rm_so >= 0)
691 else if (
match[m+=5+1].rm_so >= 0) {
692 int i = atoi(line+
match[m].rm_so);
695 if (
match[m+=2].rm_so >= 0)
697 else if (
match[++m].rm_so >= 0)
699 else if (
match[++m].rm_so >= 0)
701 else if (
match[++m].rm_so >= 0)
703 else if (
match[++m].rm_so >= 0)
708 else if (
match[m+7].rm_so >= 0)
721 pout(
"Cannot read state file \"%s\"\n", path);
725 setmode(fileno(f), O_TEXT);
729 int good = 0, bad = 0;
731 while (fgets(line,
sizeof(line), f)) {
732 const char *
s = line + strspn(line,
" \t");
733 if (!*
s || *
s ==
'#')
743 pout(
"%s: format error\n", path);
746 pout(
"%s: %d invalid line(s) ignored\n", path, bad);
757 fprintf(f,
"%s = %" PRIu64
"\n", name, val);
763 fprintf(f,
"%s.%d.%s = %" PRIu64
"\n", name1,
id, name2, val);
770 std::string pathbak = path; pathbak +=
'~';
771 unlink(pathbak.c_str());
772 rename(path, pathbak.c_str());
776 pout(
"Cannot create state file \"%s\"\n", path);
780 fprintf(f,
"# smartd state file\n");
825 pout(
"Cannot create attribute log file \"%s\"\n", path);
830 time_t now = time(
nullptr);
832 fprintf(f,
"%d-%02d-%02d %02d:%02d:%02d;",
833 1900+tms->tm_year, 1+tms->tm_mon, tms->tm_mday,
834 tms->tm_hour, tms->tm_min, tms->tm_sec);
839 fprintf(f,
"\t%d;%d;%" PRIu64
";", pa.id, pa.val, pa.raw);
843 const char * pageNames[3] = {
"read",
"write",
"verify"};
844 for (
int k = 0; k < 3; ++k) {
847 fprintf(f,
"\t%s-corr-by-ecc-fast;%" PRIu64
";"
848 "\t%s-corr-by-ecc-delayed;%" PRIu64
";"
849 "\t%s-corr-by-retry;%" PRIu64
";"
850 "\t%s-total-err-corrected;%" PRIu64
";"
851 "\t%s-corr-algorithm-invocations;%" PRIu64
";"
852 "\t%s-gb-processed;%.3f;"
853 "\t%s-total-unc-errors;%" PRIu64
";",
859 pageNames[k], (ecp->
counter[5] / 1000000000.0),
860 pageNames[k], ecp->
counter[6]);
867 fprintf(f,
"\ttemperature;%d;", state.
temperature);
877 bool write_always =
true)
879 for (
unsigned i = 0; i < states.size(); i++) {
890 PrintOut(LOG_INFO,
"Device: %s, state written to %s\n",
899 for (
unsigned i = 0; i < states.size(); i++) {
923static void USR2handler(
int sig)
954static int capabilities_mode ;
958 if (!capabilities_mode)
960 capng_clear(CAPNG_SELECT_BOTH);
961 capng_updatev(CAPNG_ADD, (capng_type_t)(CAPNG_EFFECTIVE|CAPNG_PERMITTED),
962 CAP_SYS_ADMIN, CAP_MKNOD, CAP_SYS_RAWIO, -1);
963 if (warn_as_user && (warn_uid || warn_gid)) {
965 capng_updatev(CAPNG_ADD, (capng_type_t)(CAPNG_EFFECTIVE|CAPNG_PERMITTED),
966 CAP_SETGID, CAP_SETUID, -1);
968 if (capabilities_mode > 1) {
970 capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET,
971 CAP_SETGID, CAP_SETUID, CAP_CHOWN, CAP_FOWNER, CAP_DAC_OVERRIDE, -1);
973 capng_apply(CAPNG_SELECT_BOTH);
978 if (!capabilities_mode)
980 PrintOut(LOG_INFO,
"If mail notification does not work with '--capabilities%s\n",
981 (capabilities_mode == 1 ?
"', try '--capabilities=mail'"
982 :
"=mail', please inform " PACKAGE_BUGREPORT));
1010 void set(
const char * name,
const char * value);
1017 int size = strlen(name) + 1 + strlen(value) + 1;
1018 char * newbuf =
new char[
size];
1019 snprintf(newbuf,
size,
"%s=%s", name, value);
1022 throw std::runtime_error(
"putenv() failed");
1043 static const char *
const whichfail[] = {
1049 "FailedHealthCheck",
1050 "FailedReadSmartData",
1051 "FailedReadSmartErrorLog",
1052 "FailedReadSmartSelfTestLog",
1054 "CurrentPendingSector",
1055 "OfflineUncorrectableSector",
1061 PrintOut(LOG_CRIT,
"Internal error in MailWarning(): which=%d\n", which);
1069 days = nextdays = -1;
1072 days = nextdays = -1;
break;
1074 days = nextdays = 0;
break;
1076 days = nextdays = 1;
break;
1079 nextdays = 1 << ((unsigned)mail->
logged <= 5 ? mail->
logged : 5);
1081 days = ((unsigned)mail->
logged <= 5 ? nextdays >> 1 : nextdays);
1084 PrintOut(LOG_CRIT,
"Internal error in MailWarning(): cfg.emailfreq=%d\n", (
int)cfg.
emailfreq);
1088 time_t now = time(
nullptr);
1093 if (days > 0 && now < mail->lastsent + days * 24 * 3600)
1117 std::replace(address.begin(), address.end(),
',',
' ');
1123 env[0].
set(
"SMARTD_MAILER", executable);
1124 env[1].
set(
"SMARTD_MESSAGE", message);
1126 snprintf(dates,
sizeof(dates),
"%d", mail->
logged);
1127 env[2].
set(
"SMARTD_PREVCNT", dates);
1129 env[3].
set(
"SMARTD_TFIRST", dates);
1131 env[4].
set(
"SMARTD_TFIRSTEPOCH", dates);
1132 env[5].
set(
"SMARTD_FAILTYPE", whichfail[which]);
1133 env[6].
set(
"SMARTD_ADDRESS", address.c_str());
1134 env[7].
set(
"SMARTD_DEVICESTRING", cfg.
name.c_str());
1137 env[8].
set(
"SMARTD_DEVICETYPE",
1139 env[9].
set(
"SMARTD_DEVICE", cfg.
dev_name.c_str());
1144 snprintf(dates,
sizeof(dates),
"%d", nextdays);
1145 env[11].
set(
"SMARTD_NEXTDAYS", dates);
1147 env[12].
set(
"SMARTD_SUBJECT",
"");
1151 executable =
"<mail>";
1152 const char * newadd = (!address.empty()? address.c_str() :
"<nomailer>");
1153 const char * newwarn = (which?
"Warning via" :
"Test of");
1158 snprintf(command,
sizeof(command),
"\"%s\" 2>&1",
warning_script.c_str());
1160 snprintf(command,
sizeof(command),
"%s 2>&1",
warning_script.c_str());
1164 PrintOut(LOG_INFO,
"%s %s to %s%s ...\n",
1165 (which ?
"Sending warning via" :
"Executing test of"), executable, newadd,
1167#ifdef HAVE_POSIX_API
1170 (
unsigned)warn_uid, warn_uname.c_str(),
1171 (
unsigned)warn_gid, warn_gname.c_str() ).c_str() :
1173 warn_as_restr_user ?
" (restricted user)" :
1183#ifdef HAVE_POSIX_API
1190 pfp = popen_as_restr_user(command,
"r", warn_as_restr_user);
1192 pfp = popen(command,
"r");
1198 PrintOut(LOG_CRIT,
"%s %s to %s: failed (fork or pipe failed, or no memory) %s\n",
1199 newwarn, executable, newadd, errno?strerror(errno):
"");
1210 PrintOut(LOG_CRIT,
"%s %s to %s produced unexpected output (%s%d bytes) to STDOUT/STDERR: \n%s\n",
1211 newwarn, executable, newadd, len!=newlen?
"here truncated to ":
"", newlen,
buffer);
1219 PrintOut(LOG_CRIT,
"%s %s to %s: flushed remaining STDOUT/STDERR\n",
1220 newwarn, executable, newadd);
1222 PrintOut(LOG_CRIT,
"%s %s to %s: more than 1 MB STDOUT/STDERR flushed, breaking pipe\n",
1223 newwarn, executable, newadd);
1230#ifdef HAVE_POSIX_API
1236 status = pclose(pfp);
1240 PrintOut(LOG_CRIT,
"%s %s to %s: pclose(3) failed %s\n", newwarn, executable, newadd,
1241 errno?strerror(errno):
"");
1244 if (WIFEXITED(status)) {
1246 int status8 = WEXITSTATUS(status);
1248 PrintOut(LOG_CRIT,
"%s %s to %s: failed (32-bit/8-bit exit status: %d/%d) perhaps caught signal %d [%s]\n",
1249 newwarn, executable, newadd, status, status8, status8-128, strsignal(status8-128));
1251 PrintOut(LOG_CRIT,
"%s %s to %s: failed (32-bit/8-bit exit status: %d/%d)\n",
1252 newwarn, executable, newadd, status, status8);
1256 PrintOut(LOG_INFO,
"%s %s to %s: successful\n", newwarn, executable, newadd);
1259 if (WIFSIGNALED(status))
1260 PrintOut(LOG_INFO,
"%s %s to %s: exited because of uncaught signal %d [%s]\n",
1261 newwarn, executable, newadd, WTERMSIG(status), strsignal(WTERMSIG(status)));
1265 if (WIFSTOPPED(status))
1266 PrintOut(LOG_CRIT,
"%s %s to %s: process STOPPED because it caught signal %d [%s]\n",
1267 newwarn, executable, newadd, WSTOPSIG(status), strsignal(WSTOPSIG(status)));
1296 PrintOut(LOG_INFO,
"Device: %s, %s, warning condition reset after %d email%s\n", cfg.
name.c_str(),
1308static
void vsyslog_lines(
int priority, const
char *
fmt, va_list
ap)
1313 for (
char * p = buf, * q; p && *p; p = q) {
1314 if ((q = strchr(p,
'\n')))
1317 syslog(priority,
"%s\n", p);
1323#define vsyslog_lines vsyslog
1347 vfprintf(f,
fmt,
ap);
1352 openlog(
"smartd", LOG_PID,
facility);
1353 vsyslog_lines(LOG_INFO,
fmt,
ap);
1374 vfprintf(f,
fmt,
ap);
1378 openlog(
"smartd", LOG_PID,
facility);
1379 vsyslog_lines(priority,
fmt,
ap);
1389 pout(
"Warning! %s error: invalid SMART checksum.\n",
string);
1398 int waited, max_wait = 10;
1399 struct stat stat_buf;
1404 for(waited = 0; waited < max_wait; ++waited) {
1405 if (!stat(
pid_file.c_str(), &stat_buf)) {
1429 if ((pid=fork()) < 0) {
1431 PrintOut(LOG_CRIT,
"smartd unable to fork daemon process!\n");
1447 if ((pid=fork()) < 0) {
1449 PrintOut(LOG_CRIT,
"smartd unable to fork daemon process!\n");
1460 for (
int i = sysconf(_SC_OPEN_MAX); --i >= 0; )
1464 int fd = open(
"/dev/null", O_RDWR);
1465 if (!(fd == 0 && dup(fd) == 1 && dup(fd) == 2 && !chdir(
"/"))) {
1466 PrintOut(LOG_CRIT,
"smartd unable to redirect to /dev/null or to chdir to root!\n");
1472 PrintOut(LOG_INFO,
"smartd has fork()ed into background mode. New PID=%d.\n", (
int)getpid());
1479 if (daemon_detach(
"smartd")) {
1480 PrintOut(LOG_CRIT,
"smartd unable to detach from console!\n");
1495 pid_t pid = getpid();
1498 old_umask = umask(0077);
1501 old_umask = umask(0033);
1506 if (!(f && fprintf(f,
"%d\n", (
int)pid) > 0 && f.
close())) {
1507 PrintOut(LOG_CRIT,
"unable to write PID file %s - exiting.\n",
pid_file.c_str());
1510 PrintOut(LOG_INFO,
"file %s written containing PID %d\n",
pid_file.c_str(), (
int)pid);
1525 "Configuration file (%s) Directives (after device name):\n"
1526 " -d TYPE Set the device type: auto, ignore, removable,\n"
1528 " -T TYPE Set the tolerance to one of: normal, permissive\n"
1529 " -o VAL Enable/disable automatic offline tests (on/off)\n"
1530 " -S VAL Enable/disable attribute autosave (on/off)\n"
1531 " -n MODE No check if: never, sleep[,N][,q], standby[,N][,q], idle[,N][,q]\n"
1532 " -H Monitor SMART Health Status, report if failed\n"
1533 " -s REG Do Self-Test at time(s) given by regular expression REG\n"
1534 " -l TYPE Monitor SMART log or self-test status:\n"
1535 " error, selftest, xerror, offlinests[,ns], selfteststs[,ns]\n"
1536 " -l scterc,R,W Set SCT Error Recovery Control\n"
1537 " -e Change device setting: aam,[N|off], apm,[N|off], dsn,[on|off],\n"
1538 " lookahead,[on|off], security-freeze, standby,[N|off], wcache,[on|off]\n"
1539 " -f Monitor 'Usage' Attributes, report failures\n"
1540 " -m ADD Send email warning to address ADD\n"
1541 " -M TYPE Modify email warning behavior (see man page)\n"
1542 " -p Report changes in 'Prefailure' Attributes\n"
1543 " -u Report changes in 'Usage' Attributes\n"
1544 " -t Equivalent to -p and -u Directives\n"
1545 " -r ID Also report Raw values of Attribute ID with -p, -u or -t\n"
1546 " -R ID Track changes in Attribute ID Raw value with -p, -u or -t\n"
1547 " -i ID Ignore Attribute ID for -f Directive\n"
1548 " -I ID Ignore Attribute ID for -p, -u or -t Directive\n"
1549 " -C ID[+] Monitor [increases of] Current Pending Sectors in Attribute ID\n"
1550 " -U ID[+] Monitor [increases of] Offline Uncorrectable Sectors in Attribute ID\n"
1551 " -W D,I,C Monitor Temperature D)ifference, I)nformal limit, C)ritical limit\n"
1552 " -v N,ST Modifies labeling of Attribute N (see man page) \n"
1553 " -P TYPE Drive-specific presets: use, ignore, show, showall\n"
1554 " -a Default: -H -f -t -l error -l selftest -l selfteststs -C 197 -U 198\n"
1555 " -F TYPE Use firmware bug workaround:\n"
1557 " -c i=N Set interval between disk checks to N seconds\n"
1558 " # Comment: text after a hash sign is ignored\n"
1559 " \\ Line continuation character\n"
1560 "Attribute ID is a decimal integer 1 <= ID <= 255\n"
1561 "Use ID = 0 to turn off -C and/or -U Directives\n"
1562 "Example: /dev/sda -a\n",
1564 smi()->get_valid_dev_types_str().c_str(),
1575 return "<PATH_PREFIX>, -";
1577 return "[+]<FILE_NAME>";
1579 return "<FILE_NAME>, -";
1581 return "daemon, local0, local1, local2, local3, local4, local5, local6, local7";
1583 return "nodev[0], errors[,nodev0], nodev[0]startup, never, onecheck, showtests";
1585 return "ioctl[,N], ataioctl[,N], scsiioctl[,N], nvmeioctl[,N]";
1588 return "<FILE_NAME>";
1590 return "<INTEGER_SECONDS>";
1591#ifdef HAVE_POSIX_API
1593 return "<USER>[:<GROUP>], -";
1594#elif defined(_WIN32)
1596 return "restricted, unchanged";
1598#ifdef HAVE_LIBCAP_NG
1600 return "mail, <no_argument>";
1610 PrintOut(LOG_INFO,
"Usage: smartd [options]\n\n");
1611#ifdef SMARTMONTOOLS_ATTRIBUTELOG
1612 PrintOut(LOG_INFO,
" -A PREFIX|-, --attributelog=PREFIX|-\n");
1614 PrintOut(LOG_INFO,
" -A PREFIX, --attributelog=PREFIX\n");
1616 PrintOut(LOG_INFO,
" Log attribute information to {PREFIX}MODEL-SERIAL.TYPE.csv\n");
1617#ifdef SMARTMONTOOLS_ATTRIBUTELOG
1618 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_ATTRIBUTELOG
"MODEL-SERIAL.TYPE.csv]\n");
1621 PrintOut(LOG_INFO,
" -B [+]FILE, --drivedb=[+]FILE\n");
1622 PrintOut(LOG_INFO,
" Read and replace [add] drive database from FILE\n");
1624#ifdef SMARTMONTOOLS_DRIVEDBDIR
1626 PrintOut(LOG_INFO,
" and then %s", get_drivedb_path_default());
1629 PrintOut(LOG_INFO,
" -c NAME|-, --configfile=NAME|-\n");
1630 PrintOut(LOG_INFO,
" Read configuration file NAME or stdin\n");
1632#ifdef HAVE_LIBCAP_NG
1633 PrintOut(LOG_INFO,
" -C, --capabilities[=mail]\n");
1634 PrintOut(LOG_INFO,
" Drop unneeded Linux process capabilities.\n"
1635 " Warning: Mail notification may not work when used.\n\n");
1637 PrintOut(LOG_INFO,
" -d, --debug\n");
1638 PrintOut(LOG_INFO,
" Start smartd in debug mode\n\n");
1639 PrintOut(LOG_INFO,
" -D, --showdirectives\n");
1640 PrintOut(LOG_INFO,
" Print the configuration file Directives and exit\n\n");
1641 PrintOut(LOG_INFO,
" -h, --help, --usage\n");
1642 PrintOut(LOG_INFO,
" Display this help and exit\n\n");
1643 PrintOut(LOG_INFO,
" -i N, --interval=N\n");
1644 PrintOut(LOG_INFO,
" Set interval between disk checks to N seconds, where N >= 10\n\n");
1645 PrintOut(LOG_INFO,
" -l local[0-7], --logfacility=local[0-7]\n");
1647 PrintOut(LOG_INFO,
" Use syslog facility local0 - local7 or daemon [default]\n\n");
1649 PrintOut(LOG_INFO,
" Log to \"./smartd.log\", stdout, stderr [default is event log]\n\n");
1652 PrintOut(LOG_INFO,
" -n, --no-fork\n");
1653 PrintOut(LOG_INFO,
" Do not fork into background\n");
1654#ifdef HAVE_LIBSYSTEMD
1655 PrintOut(LOG_INFO,
" (systemd 'Type=notify' is assumed if $NOTIFY_SOCKET is set)\n");
1659 PrintOut(LOG_INFO,
" -p NAME, --pidfile=NAME\n");
1660 PrintOut(LOG_INFO,
" Write PID file NAME\n\n");
1661 PrintOut(LOG_INFO,
" -q WHEN, --quit=WHEN\n");
1663 PrintOut(LOG_INFO,
" -r, --report=TYPE\n");
1665#ifdef SMARTMONTOOLS_SAVESTATES
1666 PrintOut(LOG_INFO,
" -s PREFIX|-, --savestates=PREFIX|-\n");
1668 PrintOut(LOG_INFO,
" -s PREFIX, --savestates=PREFIX\n");
1670 PrintOut(LOG_INFO,
" Save disk states to {PREFIX}MODEL-SERIAL.TYPE.state\n");
1671#ifdef SMARTMONTOOLS_SAVESTATES
1672 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_SAVESTATES
"MODEL-SERIAL.TYPE.state]\n");
1675 PrintOut(LOG_INFO,
" -w NAME, --warnexec=NAME\n");
1676 PrintOut(LOG_INFO,
" Run executable NAME on warnings\n");
1678 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_SMARTDSCRIPTDIR
"/smartd_warning.sh]\n\n");
1682#ifdef HAVE_POSIX_API
1683 PrintOut(LOG_INFO,
" -u USER[:GROUP], --warn-as-user=USER[:GROUP]\n");
1684 PrintOut(LOG_INFO,
" Run warning script as non-privileged USER\n\n");
1685#elif defined(_WIN32)
1686 PrintOut(LOG_INFO,
" -u MODE, --warn-as-user=MODE\n");
1691 PrintOut(LOG_INFO,
" Running as windows service (see man page), install with:\n");
1692 PrintOut(LOG_INFO,
" smartd install [options]\n");
1693 PrintOut(LOG_INFO,
" Remove service with:\n");
1694 PrintOut(LOG_INFO,
" smartd remove\n\n");
1696 PrintOut(LOG_INFO,
" -V, --version, --license, --copyright\n");
1697 PrintOut(LOG_INFO,
" Print License, Copyright, and version information\n");
1702 if (!device->
close()){
1713 bool changed =
false;
1714 for (
unsigned i = 0; i <
s.size(); i++) {
1718 if ((
' ' <= c && c <=
'~') && !(i == 0 && c ==
'~'))
1729 return !( (
'0' <= c && c <=
'9')
1730 || (
'A' <= c && c <=
'Z')
1731 || (
'a' <= c && c <=
'z'));
1742 PrintOut(LOG_INFO,
"Device: %s, Read Summary SMART Error Log failed\n",name);
1750 PrintOut(LOG_INFO,
"Device: %s, Read Extended Comprehensive SMART Error Log failed\n",name);
1766 PrintOut(LOG_INFO,
"Device: %s, Read SMART Self Test Log Failed\n",name);
1775 int errcnt = 0, hours = 0;
1776 for (
int i = 20; i >= 0; i--) {
1782 int status =
entry.selfteststatus >> 4;
1783 if (status == 0x0 && (
entry.selftestnumber & 0x7f) == 0x02)
1787 if (0x3 <= status && status <= 0x8) {
1792 hours =
entry.timestamp;
1796 return ((hours << 8) | errcnt);
1799#define SELFTEST_ERRORCOUNT(x) (x & 0xff)
1800#define SELFTEST_ERRORHOURS(x) ((x >> 8) & 0xffff)
1805 return ((status & 0x7f) == 0x03);
1811 return ((status >> 4) == 0xf);
1818 switch (status & 0x7f) {
1819 case 0x00: msg =
"was never started";
break;
1820 case 0x02: msg =
"was completed without error";
break;
1821 case 0x03: msg =
"is in progress";
break;
1822 case 0x04: msg =
"was suspended by an interrupting command from host";
break;
1823 case 0x05: msg =
"was aborted by an interrupting command from host";
break;
1824 case 0x06: msg =
"was aborted by the device with a fatal error";
break;
1825 default: msg =
nullptr;
1829 PrintOut(((status & 0x7f) == 0x06 ? LOG_CRIT : LOG_INFO),
1830 "Device: %s, offline data collection %s%s\n", name, msg,
1831 ((status & 0x80) ?
" (auto:on)" :
""));
1833 PrintOut(LOG_INFO,
"Device: %s, unknown offline data collection status 0x%02x\n",
1841 switch (status >> 4) {
1842 case 0x0: msg =
"completed without error";
break;
1843 case 0x1: msg =
"was aborted by the host";
break;
1844 case 0x2: msg =
"was interrupted by the host with a reset";
break;
1845 case 0x3: msg =
"could not complete due to a fatal or unknown error";
break;
1846 case 0x4: msg =
"completed with error (unknown test element)";
break;
1847 case 0x5: msg =
"completed with error (electrical test element)";
break;
1848 case 0x6: msg =
"completed with error (servo/seek test element)";
break;
1849 case 0x7: msg =
"completed with error (read test element)";
break;
1850 case 0x8: msg =
"completed with error (handling damage?)";
break;
1851 default: msg =
nullptr;
1855 PrintOut(((status >> 4) >= 0x4 ? LOG_CRIT : LOG_INFO),
1856 "Device: %s, previous self-test %s\n", name, msg);
1857 else if ((status >> 4) == 0xf)
1858 PrintOut(LOG_INFO,
"Device: %s, self-test in progress, %u0%% remaining\n",
1859 name, status & 0x0f);
1861 PrintOut(LOG_INFO,
"Device: %s, unknown self-test status 0x%02x\n",
1867 unsigned char id,
const char * msg)
1872 PrintOut(LOG_INFO,
"Device: %s, can't monitor %s count - no Attribute %d\n",
1873 cfg.
name.c_str(), msg,
id);
1881 PrintOut(LOG_INFO,
"Device: %s, ignoring %s count - bogus Attribute %d value %" PRIu64
" (0x%" PRIx64
")\n",
1882 cfg.
name.c_str(), msg,
id, rawval, rawval);
1908 int set_option = 0,
bool has_value =
false)
1915 else if (set_option < 0)
1919 else if (set_option > 0)
1929 for (
const auto & prev_cfg : prev_cfgs) {
1930 if (!prev_cfg.id_is_unique)
1935 PrintOut(LOG_INFO,
"Device: %s, same identity as %s, ignored\n",
1936 cfg.
dev_name.c_str(), prev_cfg.dev_name.c_str());
1952 const char *name = cfg.
name.c_str();
1961 PrintOut(LOG_INFO,
"Device: %s, not ATA, no IDENTIFY DEVICE Structure\n",name);
1963 PrintOut(LOG_INFO,
"Device: %s, packet devices [this device %s] not SMART capable\n",
1970 char model[40+1], serial[20+1], firmware[8+1];
1980 char wwn[64]; wwn[0] = 0;
1981 unsigned oui = 0; uint64_t unique_id = 0;
1984 snprintf(wwn,
sizeof(wwn),
"WWN:%x-%06x-%09" PRIx64
", ", naa, oui, unique_id);
2005 PrintOut(LOG_INFO,
"Device: %s, smartd database not searched (Directive: -P ignore).\n", name);
2008 std::string dbversion;
2012 PrintOut(LOG_INFO,
"Device: %s, not found in smartd database%s%s.\n", name,
2013 (!dbversion.empty() ?
" " :
""), (!dbversion.empty() ? dbversion.c_str() :
""));
2015 PrintOut(LOG_INFO,
"Device: %s, found in smartd database%s%s%s%s\n",
2016 name, (!dbversion.empty() ?
" " :
""), (!dbversion.empty() ? dbversion.c_str() :
""),
2025 bool locked = ((word128 & 0x0007) == 0x0007);
2027 PrintOut(LOG_INFO,
"Device: %s, ATA Security is **LOCKED**\n", name);
2039 PrintOut(LOG_INFO,
"Device %s: presets are:\n", name);
2051 PrintOut(LOG_INFO,
"Device: %s, lacks SMART capability\n",name);
2054 PrintOut(LOG_INFO,
"Device: %s, ATA IDENTIFY DEVICE words 82-83 don't specify if SMART capable.\n",name);
2058 PrintOut(LOG_INFO,
"Device: %s, proceeding since '-T permissive' Directive given.\n",name);
2061 PrintOut(LOG_INFO,
"Device: %s, to proceed anyway, use '-T permissive' Directive.\n",name);
2069 PrintOut(LOG_INFO,
"Device: %s, could not enable SMART capability\n",name);
2073 PrintOut(LOG_INFO,
"Device: %s, to proceed anyway, use '-T permissive' Directive.\n", name);
2077 PrintOut(LOG_INFO,
"Device: %s, proceeding since '-T permissive' Directive given.\n", name);
2080 PrintOut(LOG_INFO,
"Device: %s, proceeding since SMART is already enabled\n", name);
2087 PrintOut(LOG_INFO,
"Device: %s, could not disable SMART Attribute Autosave.\n",name);
2089 PrintOut(LOG_INFO,
"Device: %s, disabled SMART Attribute Autosave.\n",name);
2095 PrintOut(LOG_INFO,
"Device: %s, could not enable SMART Attribute Autosave.\n",name);
2097 PrintOut(LOG_INFO,
"Device: %s, enabled SMART Attribute Autosave.\n",name);
2102 PrintOut(LOG_INFO,
"Device: %s, not capable of SMART Health Status check\n",name);
2113 bool smart_val_ok =
false;
2122 PrintOut(LOG_INFO,
"Device: %s, Read SMART Values failed\n", name);
2128 smart_val_ok =
true;
2130 PrintOut(LOG_INFO,
"Device: %s, Read SMART Thresholds failed%s\n",
2131 name, (cfg.
usagefailed ?
", ignoring -f Directive" :
""));
2142 "Current_Pending_Sector"))
2147 "Offline_Uncorrectable"))
2152 PrintOut(LOG_INFO,
"Device: %s, can't monitor Temperature, ignoring -W %d,%d,%d\n",
2158 for (
int id = 1;
id <= 255;
id++) {
2166 PrintOut(LOG_INFO,
"Device: %s, no Attribute %d, ignoring -%c %d%s\n", name,
id, opt,
id, excl);
2169 if (!((prefail && cfg.
prefail) || (!prefail && cfg.
usage)))
2170 PrintOut(LOG_INFO,
"Device: %s, not monitoring %s Attributes, ignoring -%c %d%s\n", name,
2171 (prefail ?
"Prefailure" :
"Usage"), opt,
id, excl);
2182 PrintOut(LOG_INFO,
"Device: %s, could not %s SMART Automatic Offline Testing.\n",name, what);
2186 PrintOut(LOG_INFO,
"Device: %s, SMART Automatic Offline Testing unsupported...\n",name);
2189 PrintOut(LOG_INFO,
"Device: %s, %s SMART Automatic Offline Testing failed.\n", name, what);
2191 PrintOut(LOG_INFO,
"Device: %s, %sd SMART Automatic Offline Testing.\n", name, what);
2197 bool smart_logdir_ok =
false, gp_logdir_ok =
false;
2203 smart_logdir_ok =
true;
2208 gp_logdir_ok =
true;
2218 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test Log, ignoring -l selftest (override with -T permissive)\n", name);
2222 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test Log, ignoring -l selftest\n", name);
2238 PrintOut(LOG_INFO,
"Device: %s, no SMART Error Log, ignoring -l error (override with -T permissive)\n", name);
2242 PrintOut(LOG_INFO,
"Device: %s, no SMART Error Log, ignoring -l error\n", name);
2253 PrintOut(LOG_INFO,
"Device: %s, no Extended Comprehensive SMART Error Log, ignoring -l xerror (override with -T permissive)\n",
2258 PrintOut(LOG_INFO,
"Device: %s, no Extended Comprehensive SMART Error Log, ignoring -l xerror\n", name);
2262 PrintOut(LOG_INFO,
"Device: %s, SMART Error Logs report different error counts: %d != %d\n",
2276 PrintOut(LOG_INFO,
"Device: %s, no SMART Offline Data Collection capability, ignoring -l offlinests (override with -T permissive)\n", name);
2278 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test capability, ignoring -l selfteststs (override with -T permissive)\n", name);
2287 if (-1 == powermode) {
2288 PrintOut(LOG_CRIT,
"Device: %s, no ATA CHECK POWER STATUS support, ignoring -n Directive\n", name);
2291 else if (powermode!=0x00 && powermode!=0x01
2292 && powermode!=0x40 && powermode!=0x41
2293 && powermode!=0x80 && powermode!=0x81 && powermode!=0x82 && powermode!=0x83
2294 && powermode!=0xff) {
2295 PrintOut(LOG_CRIT,
"Device: %s, CHECK POWER STATUS returned %d, not ATA compliant, ignoring -n Directive\n",
2337 PrintOut(LOG_INFO,
"Device: %s, ATA settings applied: %s\n", name, msg.c_str());
2342 PrintOut(LOG_INFO,
"Device: %s, no SCT Error Recovery Control support, ignoring -l scterc\n",
2345 PrintOut(LOG_INFO,
"Device: %s, no SCT support if ATA Security is LOCKED, ignoring -l scterc\n",
2349 PrintOut(LOG_INFO,
"Device: %s, set of SCT Error Recovery Control failed\n", name);
2351 PrintOut(LOG_INFO,
"Device: %s, SCT Error Recovery Control set to: Read: %u, Write: %u\n",
2366 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n",name);
2379 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", name, cfg.
state_file.c_str());
2398 int err, req_len, avail_len, version, len;
2399 const char *device = cfg.
name.c_str();
2403 uint8_t vpdBuf[252];
2404 char lu_id[64], serial[256], vendor[40], model[40];
2407 memset(inqBuf, 0, 96);
2413 PrintOut(LOG_INFO,
"Device: %s, Both 36 and 64 byte INQUIRY failed; "
2414 "skip device\n", device);
2418 version = (inqBuf[2] & 0x7f);
2420 avail_len = inqBuf[4] + 5;
2421 len = (avail_len < req_len) ? avail_len : req_len;
2423 PrintOut(LOG_INFO,
"Device: %s, INQUIRY response less than 36 bytes; "
2424 "skip device\n", device);
2428 int pdt = inqBuf[0] & 0x1f;
2439 PrintOut(LOG_INFO,
"Device: %s, not a disk like device [PDT=0x%x], "
2440 "skip\n", device, pdt);
2451 if (version >= 0x3) {
2454 vpdBuf,
sizeof(vpdBuf))) {
2461 vpdBuf,
sizeof(vpdBuf))) {
2463 vpdBuf[4 + len] =
'\0';
2478 (
char *)&inqBuf[8], (
char *)&inqBuf[16], (
char *)&inqBuf[32],
2479 (lu_id[0] ?
", lu id: " :
""), (lu_id[0] ? lu_id :
""),
2480 (serial[0] ?
", S/N: " :
""), (serial[0] ? serial :
""),
2481 (si_str[0] ?
", " :
""), (si_str[0] ? si_str :
""));
2501 PrintOut(LOG_INFO,
"Device: %s, NOT READY (e.g. spun down); skip device\n", device);
2503 PrintOut(LOG_INFO,
"Device: %s, NO MEDIUM present; skip device\n", device);
2505 PrintOut(LOG_INFO,
"Device: %s, BECOMING (but not yet) READY; skip device\n", device);
2507 PrintOut(LOG_CRIT,
"Device: %s, failed Test Unit Ready [err=%d]\n", device, err);
2524 "Device: %s, Bad IEC (SMART) mode page, err=%d, skip device\n",
2533 PrintOut(LOG_INFO,
"Device: %s, IE (SMART) not enabled, skip device\n"
2534 "Try 'smartctl -s on %s' to turn on SMART features\n",
2576 uint8_t currenttemp = 0;
2577 uint8_t triptemp = 0;
2580 &asc, &ascq, ¤ttemp, &triptemp)) {
2581 PrintOut(LOG_INFO,
"Device: %s, unexpectedly failed to read SMART values\n", device);
2586 PrintOut(LOG_INFO,
"Device: %s, can't monitor Temperature, ignoring -W %d,%d,%d\n",
2597 PrintOut(LOG_INFO,
"Device: %s, does not support SMART Self-Test Log.\n", device);
2612 PrintOut(LOG_INFO,
"Device: %s, could not disable autosave (set GLTSD bit).\n",device);
2614 PrintOut(LOG_INFO,
"Device: %s, disabled autosave (set GLTSD bit).\n",device);
2620 PrintOut(LOG_INFO,
"Device: %s, could not enable autosave (clear GLTSD bit).\n",device);
2622 PrintOut(LOG_INFO,
"Device: %s, enabled autosave (cleared GLTSD bit).\n",device);
2626 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n", device);
2642 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", device, cfg.
state_file.c_str());
2659 for (
int i = 8; i < 16; i++) {
2661 return ~(uint64_t)0;
2663 uint64_t lo = val[7];
2664 for (
int i = 7-1; i >= 0; i--) {
2665 lo <<= 8; lo += val[i];
2684 const char *name = cfg.
name.c_str();
2691 PrintOut(LOG_INFO,
"Device: %s, NVMe Identify Controller failed\n", name);
2697 char model[40+1], serial[20+1], firmware[8+1];
2703 char nsstr[32] =
"", capstr[32] =
"";
2705 if (
nsid != 0xffffffff)
2706 snprintf(nsstr,
sizeof(nsstr),
", NSID:%u",
nsid);
2711 nsstr, (capstr[0] ?
", " :
""), capstr);
2727 PrintOut(LOG_INFO,
"Device: %s, failed to read NVMe SMART/Health Information\n", name);
2735 PrintOut(LOG_INFO,
"Device: %s, no Temperature sensors, ignoring -W %d,%d,%d\n",
2754 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n", name);
2766 if (
nsid != 0xffffffff)
2767 snprintf(nsstr,
sizeof(nsstr),
"-n%u",
nsid);
2771 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", name, cfg.
state_file.c_str());
2783 const char * name = cfg.
name.c_str();
2787 MailWarning(cfg, state, 0,
"TEST EMAIL from smartd for device: %s", name);
2802 PrintOut(LOG_INFO,
"Device: %s, is in %s mode, suspending checks\n", name,
"STANDBY (OS)");
2813 if (!device->
open()) {
2816 PrintOut(LOG_INFO,
"Device: %s, open() of %s device failed: %s\n", name, type, device->
get_errmsg());
2817 MailWarning(cfg, state, 9,
"Device: %s, unable to open %s device", name, type);
2820 PrintOut(LOG_INFO,
"Device: %s, removed %s device: %s\n", name, type, device->
get_errmsg());
2824 PrintOut(LOG_INFO,
"Device: %s, %s device still removed: %s\n", name, type, device->
get_errmsg());
2829 PrintOut(LOG_INFO,
"Device: %s, opened %s device\n", name, type);
2834 PrintOut(LOG_INFO,
"Device: %s, reconnected %s device\n", name, type);
2845 const char * name = cfg.
name.c_str();
2849 MailWarning(cfg, state, 8,
"Device: %s, Read SMART Self-Test Log Failed", name);
2863 PrintOut(LOG_CRIT,
"Device: %s, Self-Test Log error count increased from %d to %d\n",
2865 MailWarning(cfg, state, 3,
"Device: %s, Self-Test Log error count increased from %d to %d",
2869 else if (newc > 0 && oldh != newh) {
2877 PrintOut(LOG_CRIT,
"Device: %s, new Self-Test Log error at hour timestamp %d\n",
2879 MailWarning(cfg, state, 3,
"Device: %s, new Self-Test Log error at hour timestamp %d",
2887 PrintOut(LOG_INFO,
"Device: %s, Self-Test Log error count decreased from %d to %d\n",
2924 time_t now = (!usetime ? time(
nullptr) : usetime);
2938 unsigned offsets[max_offsets] = {0, }, limits[max_offsets] = {0, };
2939 unsigned num_offsets = 1;
2941 const char * q = strchr(p,
':');
2945 unsigned offset = 0, limit = 0;
int n1 = -1, n2 = -1, n3 = -1;
2946 sscanf(p,
"%u%n-%n%u%n", &offset, &n1, &n2, &limit, &n3);
2947 if (!(n1 == 3 && (n2 < 0 || (n3 == 3+1+3 && limit > 0))))
2949 offsets[num_offsets] = offset; limits[num_offsets] = limit;
2951 p += (n3 > 0 ? n3 : n1);
2956 time_t testtime = 0;
int testhour = 0;
2961 for (
unsigned i = 0; i < num_offsets; i++) {
2962 unsigned offset = offsets[i], limit = limits[i];
2964 if (0 < limit && limit < delay)
2969 int weekday = (tms->tm_wday ? tms->tm_wday : 7);
2970 for (
int j = 0; j <= maxtest; j++) {
2983 snprintf(pattern,
sizeof(pattern),
"%c/%02d/%02d/%1d/%02d",
2984 test_type_chars[j], tms->tm_mon+1, tms->tm_mday, weekday, tms->tm_hour);
2986 const unsigned len =
sizeof(
"S/01/01/1/01") - 1;
2987 snprintf(pattern + len,
sizeof(pattern) - len,
":%03u", offset);
2989 snprintf(pattern + len + 4,
sizeof(pattern) - len - 4,
"-%03u", limit);
2993 testtype = pattern[0];
2994 testtime = t; testhour = tms->tm_hour;
3008 if ((t += 3600) > now)
3019 if (!usetime && !(testhour == tmnow->tm_hour && testtime + 3600 > now)) {
3021 PrintOut(LOG_INFO,
"Device: %s, old test of type %c not run at %s, starting now.\n",
3022 cfg.
name.c_str(), testtype, datebuf);
3032 unsigned numdev = configs.size();
3037 PrintOut(LOG_INFO,
"\nNext scheduled self tests (at most 5 of each type per device):\n");
3040 time_t now = time(
nullptr);
3047 time_t testtime = now + seconds;
3048 for (
unsigned i = 0; i < numdev; i++) {
3058 PrintOut(LOG_INFO,
"Device: %s, will do test %d of type %c at %s\n", cfg.
name.c_str(),
3067 PrintOut(LOG_INFO,
"\nTotals [%s - %s]:\n", datenow, date);
3068 for (
unsigned i = 0; i < numdev; i++) {
3070 bool scsi =
devices.at(i)->is_scsi();
3075 PrintOut(LOG_INFO,
"Device: %s, will do %3d test%s of type %c\n", cfg.
name.c_str(),
3087 const char *testname =
nullptr;
3088 const char *name = cfg.
name.c_str();
3092 PrintOut(LOG_CRIT,
"Device: %s, does not support Self-Tests\n", name);
3097 if (1 == inProgress) {
3098 PrintOut(LOG_INFO,
"Device: %s, skip since Self-Test already in "
3099 "progress.\n", name);
3105 testname =
"Short Self";
3109 testname =
"Long Self";
3115 PrintOut(LOG_CRIT,
"Device: %s, not capable of %c Self-Test\n", name,
3122 PrintOut(LOG_CRIT,
"Device: %s, not capable of %s-Test\n", name,
3131 PrintOut(LOG_CRIT,
"Device: %s, execute %s-Test failed (err: %d)\n", name,
3136 PrintOut(LOG_INFO,
"Device: %s, starting scheduled %s-Test.\n", name, testname);
3145 const char *name = cfg.
name.c_str();
3150 PrintOut(LOG_CRIT,
"Device: %s, not capable of Offline or Self-Testing.\n", name);
3155 int dotest = -1, mode = 0;
3156 const char *testname =
nullptr;
3159 testname=
"Offline Immediate ";
3166 testname=
"Conveyance Self-";
3173 testname=
"Short Self-";
3180 testname=
"Long Self-";
3187 case 'c':
case 'n':
case 'r':
3188 testname =
"Selective Self-";
3204 PrintOut(LOG_CRIT,
"Device: %s, not capable of %sTest\n", name, testname);
3209 if (15==(
data.self_test_exec_status >> 4)) {
3211 PrintOut(LOG_INFO,
"Device: %s, will not skip scheduled %sTest "
3212 "despite unclear Self-Test byte (SAMSUNG Firmware bug).\n", name, testname);
3214 PrintOut(LOG_INFO,
"Device: %s, skip scheduled %sTest; %1d0%% remaining of current Self-Test.\n",
3215 name, testname, (
int)(
data.self_test_exec_status & 0x0f));
3229 PrintOut(LOG_CRIT,
"Device: %s, prepare %sTest failed\n", name, testname);
3233 PrintOut(LOG_INFO,
"Device: %s, %s test span at LBA %" PRIu64
" - %" PRIu64
" (%" PRIu64
" sectors, %u%% - %u%% of disk).\n",
3235 start, end, end - start + 1,
3245 PrintOut(LOG_CRIT,
"Device: %s, execute %sTest failed.\n", name, testname);
3251 if (testtype ==
'O')
3256 PrintOut(LOG_INFO,
"Device: %s, starting scheduled %sTest.\n", name, testname);
3262 unsigned char id,
bool increase_only,
3264 int mailtype,
const char * msg)
3280 if (!(!increase_only || prev_rawval < rawval))
3284 std::string
s =
strprintf(
"Device: %s, %" PRId64
" %s", cfg.
name.c_str(), rawval, msg);
3285 if (prev_rawval > 0 && rawval != prev_rawval)
3286 s +=
strprintf(
" (changed %+" PRId64
")", rawval - prev_rawval);
3294static const char *
fmt_temp(
unsigned char x,
char (& buf)[20])
3298 snprintf(buf,
sizeof(buf),
"%u", x);
3305 if (!(0 < currtemp && currtemp < 255)) {
3306 PrintOut(LOG_INFO,
"Device: %s, failed to read Temperature\n", cfg.
name.c_str());
3311 const char * minchg =
"", * maxchg =
"";
3312 if (currtemp > state.
tempmax) {
3325 PrintOut(LOG_INFO,
"Device: %s, initial Temperature is %d Celsius (Min/Max %s/%u%s)\n",
3328 PrintOut(LOG_INFO,
" [trip Temperature is %d Celsius]\n", (
int)triptemp);
3352 PrintOut(LOG_INFO,
"Device: %s, Temperature changed %+d Celsius to %u Celsius (Min/Max %s%s/%u%s)\n",
3360 PrintOut(LOG_CRIT,
"Device: %s, Temperature %u Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)\n",
3362 MailWarning(cfg, state, 12,
"Device: %s, Temperature %d Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)",
3366 PrintOut(LOG_INFO,
"Device: %s, Temperature %u Celsius reached limit of %u Celsius (Min/Max %s%s/%u%s)\n",
3371 if (currtemp < limit)
3372 reset_warning_mail(cfg, state, 12,
"Temperature %u Celsius dropped below %u Celsius", currtemp, limit);
3392 PrintOut(LOG_CRIT,
"Device: %s, Failed SMART usage Attribute: %d %s.\n", cfg.
name.c_str(), attr.
id, attrname.c_str());
3393 MailWarning(cfg, state, 2,
"Device: %s, Failed SMART usage Attribute: %d %s.", cfg.
name.c_str(), attr.
id, attrname.c_str());
3399 if (!( ( prefail && cfg.
prefail)
3400 || (!prefail && cfg.
usage )))
3408 if (attr.
id != prev.
id) {
3409 PrintOut(LOG_INFO,
"Device: %s, same Attribute has different ID numbers: %d = %d\n",
3410 cfg.
name.c_str(), attr.
id, prev.
id);
3415 bool valchanged =
false;
3422 bool rawchanged =
false;
3430 if (!(valchanged || rawchanged))
3434 std::string currstr, prevstr;
3456 std::string msg =
strprintf(
"Device: %s, SMART %s Attribute: %d %s changed from %s to %s",
3457 cfg.
name.c_str(), (prefail ?
"Prefailure" :
"Usage"), attr.
id,
3459 prevstr.c_str(), currstr.c_str());
3464 PrintOut(LOG_CRIT,
"%s\n", msg.c_str());
3468 PrintOut(LOG_INFO,
"%s\n", msg.c_str());
3475 bool firstpass,
bool allow_selftests)
3480 const char * name = cfg.
name.c_str();
3487 const char * mode = 0;
3488 if (0 <= powermode && powermode < 0xff) {
3493 if (powermode2 > powermode)
3494 PrintOut(LOG_INFO,
"Device: %s, CHECK POWER STATUS spins up disk (0x%02x -> 0x%02x)\n", name, powermode, powermode2);
3495 powermode = powermode2;
3547 mode=
"ACTIVE or IDLE";
3551 PrintOut(LOG_CRIT,
"Device: %s, CHECK POWER STATUS returned %d, not ATA compliant, ignoring -n Directive\n",
3564 PrintOut(LOG_INFO,
"Device: %s, is in %s mode, suspending checks\n", name, mode);
3571 PrintOut(LOG_INFO,
"Device: %s, %s mode ignored due to reached limit of skipped checks (%d check%s skipped)\n",
3578 PrintOut(LOG_INFO,
"Device: %s, is back in %s mode, resuming checks (%d check%s skipped)\n",
3589 PrintOut(LOG_INFO,
"Device: %s, not capable of SMART self-check\n",name);
3590 MailWarning(cfg, state, 5,
"Device: %s, not capable of SMART self-check", name);
3593 else if (status==1){
3594 PrintOut(LOG_CRIT,
"Device: %s, FAILED SMART self-check. BACK UP DATA NOW!\n", name);
3595 MailWarning(cfg, state, 1,
"Device: %s, FAILED SMART self-check. BACK UP DATA NOW!", name);
3609 PrintOut(LOG_CRIT,
"Device: %s, failed to read SMART Attribute Data\n", name);
3610 MailWarning(cfg, state, 6,
"Device: %s, failed to read SMART Attribute Data", name);
3620 :
"Total unreadable (pending) sectors" ));
3625 :
"Total offline uncorrectable sectors"));
3671 int errcnt1 = -1, errcnt2 = -1;
3678 int newc = (errcnt1 >= errcnt2 ? errcnt1 : errcnt2);
3683 MailWarning(cfg, state, 7,
"Device: %s, Read SMART Error Log Failed", name);
3688 PrintOut(LOG_CRIT,
"Device: %s, ATA error count increased from %d to %d\n",
3690 MailWarning(cfg, state, 4,
"Device: %s, ATA error count increased from %d to %d",
3723 const char * name = cfg.
name.c_str();
3725 uint8_t asc = 0, ascq = 0;
3726 uint8_t currenttemp = 0, triptemp = 0;
3729 &asc, &ascq, ¤ttemp, &triptemp)) {
3730 PrintOut(LOG_INFO,
"Device: %s, failed to read SMART values\n",
3732 MailWarning(cfg, state, 6,
"Device: %s, failed to read SMART values", name);
3741 PrintOut(LOG_CRIT,
"Device: %s, SMART Failure: %s\n", name, cp);
3742 MailWarning(cfg, state, 1,
"Device: %s, SMART Failure: %s", name, cp);
3743 }
else if (asc == 4 && ascq == 9) {
3744 PrintOut(LOG_INFO,
"Device: %s, self-test in progress\n", name);
3746 PrintOut(LOG_INFO,
"Device: %s, non-SMART asc,ascq: %d,%d\n",
3747 name, (
int)asc, (
int)ascq);
3749 PrintOut(LOG_INFO,
"Device: %s, SMART health: passed\n", name);
3805 const char * name = cfg.
name.c_str();
3811 PrintOut(LOG_INFO,
"Device: %s, failed to read NVMe SMART/Health Information\n", name);
3812 MailWarning(cfg, state, 6,
"Device: %s, failed to read NVMe SMART/Health Information", name);
3821 static const char *
const wnames[] =
3822 {
"LowSpare",
"Temperature",
"Reliability",
"R/O",
"VolMemBackup"};
3824 for (
unsigned b = 0, cnt = 0;
b < 8 ;
b++) {
3825 if (!(
w & (1 <<
b)))
3830 msg +=
"...";
break;
3832 if (
b >=
sizeof(wnames)/
sizeof(wnames[0])) {
3833 msg +=
"*Unknown*";
break;
3838 PrintOut(LOG_CRIT,
"Device: %s, Critical Warning (0x%02x): %s\n", name,
w, msg.c_str());
3839 MailWarning(cfg, state, 1,
"Device: %s, Critical Warning (0x%02x): %s", name,
w, msg.c_str());
3859 if (newcnt > oldcnt) {
3860 PrintOut(LOG_CRIT,
"Device: %s, number of Error Log entries increased from %" PRIu64
" to %" PRIu64
"\n",
3861 name, oldcnt, newcnt);
3862 MailWarning(cfg, state, 4,
"Device: %s, number of Error Log entries increased from %" PRIu64
" to %" PRIu64,
3863 name, oldcnt, newcnt);
3880 bool sts1 =
false, sts2 =
false;
3881 for (
const auto & cfg : configs) {
3882 if (cfg.offlinests_ns)
3884 if (cfg.selfteststs_ns)
3891 if (!
smi()->disable_system_auto_standby(
false)) {
3893 PrintOut(LOG_CRIT,
"System auto standby enable failed: %s\n",
smi()->get_errmsg());
3895 PrintOut(LOG_INFO,
"Disable auto standby not supported, ignoring ',ns' from %s%s%s\n",
3896 (sts1 ?
"-l offlinests,ns" :
""), (sts1 && sts2 ?
" and " :
""), (sts2 ?
"-l selfteststs,ns" :
""));
3897 sts1 = sts2 =
false;
3911 bool running =
false;
3912 for (
unsigned i = 0; i < configs.size() && !running; i++) {
3928 if (!
smi()->disable_system_auto_standby(
false))
3929 PrintOut(LOG_CRIT,
"Self-test(s) completed, system auto standby enable failed: %s\n",
3930 smi()->get_errmsg());
3932 PrintOut(LOG_INFO,
"Self-test(s) completed, system auto standby enabled\n");
3936 else if (!
smi()->disable_system_auto_standby(
true)) {
3938 PrintOut(LOG_INFO,
"Self-test(s) in progress, system auto standby disable rejected: %s\n",
3939 smi()->get_errmsg());
3945 PrintOut(LOG_INFO,
"Self-test(s) in progress, system auto standby disabled\n");
3955 for (
unsigned i = 0; i < configs.size(); i++) {
3960 PrintOut(LOG_INFO,
"Device: %s, skipped (interval=%d)\n", cfg.
name.c_str(),
4001static void ToggleDebugMode()
4004 PrintOut(LOG_INFO,
"Signal USR2 - enabling debug mode\n");
4005 if (!daemon_enable_console(
"smartd [Debug]")) {
4008 PrintOut(LOG_INFO,
"smartd debug mode enabled, PID=%d\n", getpid());
4011 PrintOut(LOG_INFO,
"enable console failed\n");
4014 daemon_disable_console();
4017 PrintOut(LOG_INFO,
"Signal USR2 - debug mode disabled\n");
4026 if (timenow < wakeuptime)
4028 return timenow + ct - (timenow - wakeuptime) % ct;
4035 time_t timenow = time(
nullptr);
4036 unsigned n = configs.size();
4046 for (
unsigned i = 0; i < n; i++) {
4052 if (!wakeuptime || state.
wakeuptime < wakeuptime)
4061 bool no_skip =
false;
4065 if (wakeuptime > timenow + ct) {
4066 PrintOut(LOG_INFO,
"System clock time adjusted to the past. Resetting next wakeup time.\n");
4067 wakeuptime = timenow + ct;
4068 for (
auto & state : states)
4069 state.wakeuptime = 0;
4074 sleep(wakeuptime+addtime-timenow);
4078 if (caughtsigUSR2) {
4084 timenow = time(
nullptr);
4087 if (!addtime && timenow > wakeuptime+60) {
4089 PrintOut(LOG_INFO,
"Sleep time was %d seconds too long, assuming wakeup from standby mode.\n",
4090 (
int)(timenow-wakeuptime));
4092 addtime = timenow-wakeuptime+20;
4094 int nextcheck = ct - addtime % ct;
4095 if (nextcheck <= 20)
4096 addtime += nextcheck;
4102 PrintOut(LOG_INFO,
"Signal USR1 - checking devices now rather than in %d seconds.\n",
4103 wakeuptime-timenow>0?(
int)(wakeuptime-timenow):0);
4105 sigwakeup = no_skip =
true;
4110 for (
auto & state : states)
4111 state.skip = (!no_skip && timenow < state.wakeuptime);
4123 PrintOut(priority,
"never[,N][,q], sleep[,N][,q], standby[,N][,q], idle[,N][,q]");
4126 PrintOut(priority,
"valid_regular_expression");
4129 PrintOut(priority,
"%s",
smi()->get_valid_dev_types_str().c_str());
4132 PrintOut(priority,
"normal, permissive");
4139 PrintOut(priority,
"error, selftest");
4142 PrintOut(priority,
"\"once\", \"always\", \"daily\", \"diminishing\", \"test\", \"exec\"");
4148 PrintOut(priority,
"use, ignore, show, showall");
4154 PrintOut(priority,
"aam,[N|off], apm,[N|off], lookahead,[on|off], dsn,[on|off] "
4155 "security-freeze, standby,[N|off], wcache,[on|off]");
4158 PrintOut(priority,
"i=N, interval=N");
4164static int GetInteger(
const char *arg,
const char *name,
const char *token,
int lineno,
const char *cfgfile,
4165 int min,
int max,
char * suffix = 0)
4169 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s takes integer argument from %d to %d.\n",
4170 cfgfile, lineno, name, token, min, max);
4176 int val = strtol(arg,&endptr,10);
4180 if (!strcmp(endptr, suffix))
4181 endptr += strlen(suffix);
4186 if (!(!*endptr && min <= val && val <= max)) {
4187 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s has argument: %s; needs integer from %d to %d.\n",
4188 cfgfile, lineno, name, token, arg, min, max);
4198static int Get3Integers(
const char *arg,
const char *name,
const char *token,
int lineno,
const char *cfgfile,
4199 unsigned char *val1,
unsigned char *val2,
unsigned char *val3)
4201 unsigned v1 = 0, v2 = 0, v3 = 0;
4202 int n1 = -1, n2 = -1, n3 = -1, len;
4204 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s takes 1-3 integer argument(s) from 0 to 255.\n",
4205 cfgfile, lineno, name, token);
4210 if (!( sscanf(arg,
"%u%n,%u%n,%u%n", &v1, &n1, &v2, &n2, &v3, &n3) >= 1
4211 && (n1 == len || n2 == len || n3 == len) && v1 <= 255 && v2 <= 255 && v3 <= 255)) {
4212 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s has argument: %s; needs 1-3 integer(s) from 0 to 255.\n",
4213 cfgfile, lineno, name, token, arg);
4216 *val1 = (
unsigned char)v1; *val2 = (
unsigned char)v2; *val3 = (
unsigned char)v3;
4224static const char * strtok_dequote(
const char * delimiters)
4226 const char * t = strtok(
nullptr, delimiters);
4227 if (!t || t[0] !=
'"')
4230 static std::string token;
4233 t = strtok(
nullptr, delimiters);
4237 int len = strlen(t);
4238 if (t[len-1] ==
'"') {
4239 token += std::string(t, len-1);
4244 return token.c_str();
4256 const char * name = cfg.
name.c_str();
4258 const char *delim =
" \n\t";
4261 const char *arg = 0;
4268 if (*token!=
'-' || strlen(token)!=2) {
4269 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): unknown Directive: %s\n",
4271 PrintOut(LOG_CRIT,
"Run smartd -D to print a list of valid Directives.\n");
4280 char plus[] =
"+", excl[] =
"!";
4285 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 0, 255, plus)) < 0)
4293 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 0, 255, plus)) < 0)
4301 if (!(arg = strtok(
nullptr, delim))) {
4303 }
else if (!strcmp(arg,
"normal")) {
4308 }
else if (!strcmp(arg,
"permissive")) {
4317 if (!(arg = strtok(
nullptr, delim))) {
4319 }
else if (!strcmp(arg,
"ignore")) {
4321 }
else if (!strcmp(arg,
"removable")) {
4323 }
else if (!strcmp(arg,
"auto")) {
4328 scan_types.push_back(arg);
4333 if (!(arg = strtok(
nullptr, delim)))
4361 if (!(arg = strtok(
nullptr, delim))) {
4363 }
else if (!strcmp(arg,
"selftest")) {
4366 }
else if (!strcmp(arg,
"error")) {
4369 }
else if (!strcmp(arg,
"xerror")) {
4372 }
else if (!strcmp(arg,
"offlinests")) {
4375 }
else if (!strcmp(arg,
"offlinests,ns")) {
4378 }
else if (!strcmp(arg,
"selfteststs")) {
4381 }
else if (!strcmp(arg,
"selfteststs,ns")) {
4384 }
else if (!strncmp(arg,
"scterc,",
sizeof(
"scterc,")-1)) {
4386 unsigned rt = ~0, wt = ~0;
int nc = -1;
4387 sscanf(arg,
"scterc,%u,%u%n", &rt, &wt, &nc);
4388 if (nc == (
int)strlen(arg) && rt <= 999 && wt <= 999) {
4411 if (!(arg = strtok(
nullptr, delim))) {
4413 }
else if (!strcmp(arg,
"on")) {
4415 }
else if (!strcmp(arg,
"off")) {
4423 if (!(arg = strtok(
nullptr, delim)))
4426 char *endptr =
nullptr;
4427 char *next = strchr(
const_cast<char*
>(arg),
',');
4434 if (!strcmp(arg,
"never"))
4436 else if (!strcmp(arg,
"sleep"))
4438 else if (!strcmp(arg,
"standby"))
4440 else if (!strcmp(arg,
"idle"))
4446 if (!badarg && next) {
4452 next = endptr + (*endptr !=
'\0');
4456 if (*next !=
'\0') {
4457 if (!strcmp(
"q", next))
4468 if (!(arg = strtok(
nullptr, delim))) {
4470 }
else if (!strcmp(arg,
"on")) {
4472 }
else if (!strcmp(arg,
"off")) {
4481 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous Test Directive -s %s\n",
4486 if (!(arg = strtok(
nullptr, delim))) {
4493 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): -s argument \"%s\" is INVALID extended regular expression. %s.\n",
4502 "[^]$()*+./:?^[|0-9LSCOncr-]+|"
4503 ":[0-9]{0,2}($|[^0-9])|:[0-9]{4,}|"
4504 ":[0-9]{3}-(000|[0-9]{0,2}($|[^0-9])|[0-9]{4,})"
4507 if (syntax_check.
execute(arg, 1, &range) && 0 <= range.rm_so && range.rm_so < range.rm_eo)
4508 PrintOut(LOG_INFO,
"File %s line %d (drive %s): warning, \"%.*s\" looks odd in "
4509 "extended regular expression \"%s\"\n",
4510 configfile, lineno, name, (
int)(range.rm_eo - range.rm_so), arg + range.rm_so, arg);
4515 if (!(arg = strtok(
nullptr, delim)))
4519 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous Address Directive -m %s\n",
4526 if (!(arg = strtok(
nullptr, delim)))
4528 else if (!strcmp(arg,
"once"))
4530 else if (!strcmp(arg,
"always"))
4532 else if (!strcmp(arg,
"daily"))
4534 else if (!strcmp(arg,
"diminishing"))
4536 else if (!strcmp(arg,
"test"))
4538 else if (!strcmp(arg,
"exec")) {
4542 arg = strtok_dequote(delim);
4543 if (arg && arg[0] ==
'"') {
4544 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive %s 'exec' argument: missing closing quote\n",
4549 arg = strtok(
nullptr, delim);
4552 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive %s 'exec' argument must be followed by executable path.\n",
4558 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous mail Directive -M exec %s\n",
4567 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255)) < 0)
4573 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255)) < 0)
4579 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255, excl)) < 0)
4587 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255, excl)) < 0)
4601 if (!(arg = strtok(
nullptr, delim))) {
4609 if (!(arg = strtok(
nullptr, delim))) {
4611 }
else if (!strcmp(arg,
"use")) {
4613 }
else if (!strcmp(arg,
"ignore")) {
4615 }
else if (!strcmp(arg,
"show")) {
4617 }
else if (!strcmp(arg,
"showall")) {
4626 if (!(arg = strtok(
nullptr, delim))) {
4630 char arg2[16+1];
unsigned uval;
4631 int n1 = -1, n2 = -1, n3 = -1, len = strlen(arg);
4632 if (sscanf(arg,
"%16[^,=]%n%*[,=]%n%u%n", arg2, &n1, &n2, &uval, &n3) >= 1
4633 && (n1 == len || n2 > 0)) {
4634 bool on = (n2 > 0 && !strcmp(arg+n2,
"on"));
4635 bool off = (n2 > 0 && !strcmp(arg+n2,
"off"));
4639 if (!strcmp(arg2,
"aam")) {
4642 else if (uval <= 254)
4647 else if (!strcmp(arg2,
"apm")) {
4650 else if (1 <= uval && uval <= 254)
4655 else if (!strcmp(arg2,
"lookahead")) {
4663 else if (!strcmp(arg,
"security-freeze")) {
4666 else if (!strcmp(arg2,
"standby")) {
4669 else if (uval <= 255)
4674 else if (!strcmp(arg2,
"wcache")) {
4682 else if (!strcmp(arg2,
"dsn")) {
4701 if (!(arg = strtok(
nullptr, delim))) {
4705 int n = 0, nc = -1, len = strlen(arg);
4706 if ( ( sscanf(arg,
"i=%d%n", &n, &nc) == 1
4707 || sscanf(arg,
"interval=%d%n", &n, &nc) == 1)
4708 && nc == len && n >= 10)
4717 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): unknown Directive: %s\n",
4719 PrintOut(LOG_CRIT,
"Run smartd -D to print a list of valid Directives.\n");
4723 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Missing argument to %s Directive\n",
4727 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Invalid argument to %s Directive: %s\n",
4730 if (missingarg || badarg) {
4731 PrintOut(LOG_CRIT,
"Valid arguments to %s Directive are: ", token);
4741#define SCANDIRECTIVE "DEVICESCAN"
4755 const char *delim =
" \n\t";
4758 const char * name = strtok(line, delim);
4759 if (!name || *name ==
'#')
4764 if (!strcmp(
"DEFAULT", name)) {
4772 conf_entries.push_back(default_conf);
4774 dev_config & cfg = (retval ? conf_entries.back() : default_conf);
4781 while (
char * token = strtok(
nullptr, delim)) {
4795 if (retval != -1 && scan_types.size() > 1) {
4796 PrintOut(LOG_CRIT,
"Drive: %s, invalid multiple -d TYPE Directives on line %d of file %s\n",
4812 PrintOut(LOG_INFO,
"Drive: %s, implied '-a' Directive on line %d of file %s\n",
4827 PrintOut(LOG_CRIT,
"Drive: %s, -M Directive(s) on line %d of file %s need -m ADDRESS Directive\n",
4836 PrintOut(LOG_CRIT,
"Drive: %s, -m <nomailer> Directive on line %d of file %s needs -M exec Directive\n",
4861 const int MAXLINELEN = 256;
4863 const int MAXCONTLINE = 1023;
4870 int ret = (errno!=ENOENT ? -3 : -2);
4871 PrintOut(LOG_CRIT,
"%s: Unable to open configuration file %s\n",
4887 if (
ParseConfigLine(conf_entries, default_conf, scan_types, 0, fakeconfig) != -1)
4888 throw std::logic_error(
"Internal error parsing " SCANDIRECTIVE);
4893 setmode(fileno(f), O_TEXT);
4900 int lineno = 1, cont = 0, contlineno = 0;
4901 char line[MAXLINELEN+2];
4902 char fullline[MAXCONTLINE+1];
4905 int len=0,scandevice;
4911 memset(line,0,
sizeof(line));
4914 code=fgets(line, MAXLINELEN+2, f);
4919 scandevice =
ParseConfigLine(conf_entries, default_conf, scan_types, contlineno, fullline);
4937 if (len>MAXLINELEN){
4939 if (line[len-1]==
'\n')
4940 warn=
"(including newline!) ";
4943 PrintOut(LOG_CRIT,
"Error: line %d of file %s %sis more than MAXLINELEN=%d characters.\n",
4944 (
int)contlineno,
configfile,warn,(
int)MAXLINELEN);
4949 if ((comment=strchr(line,
'#'))){
4955 if (cont+len>MAXCONTLINE){
4956 PrintOut(LOG_CRIT,
"Error: continued line %d (actual line %d) of file %s is more than MAXCONTLINE=%d characters.\n",
4957 lineno, (
int)contlineno,
configfile, (
int)MAXCONTLINE);
4962 snprintf(fullline+cont,
sizeof(fullline)-cont,
"%s" ,line);
4966 if ( (lastslash=strrchr(line,
'\\')) && !strtok(lastslash+1,
" \n\t")){
4967 *(fullline+(cont-len)+(lastslash-line))=
' ';
4973 scandevice =
ParseConfigLine(conf_entries, default_conf, scan_types, contlineno, fullline);
4997 PrintOut(LOG_CRIT,
"=======> VALID ARGUMENTS ARE: ");
4999 PrintOut(LOG_CRIT,
"Error constructing argument list for option %c", opt);
5009 if (path.empty() || path[0] ==
'/')
5014 PrintOut(LOG_CRIT,
"=======> INVALID ARGUMENT TO -%c: %s <=======\n\n", option, path.c_str());
5015 PrintOut(LOG_CRIT,
"Error: relative path names are not allowed\n\n");