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);
136#define EXIT_BADCONF 2
137#define EXIT_STARTUP 3
140#define EXIT_READCONF 6
143#define EXIT_BADCODE 10
145#define EXIT_BADDEV 16
148#define EXIT_SIGNAL 254
164#ifdef SMARTMONTOOLS_SAVESTATES
165 = SMARTMONTOOLS_SAVESTATES
171#ifdef SMARTMONTOOLS_ATTRIBUTELOG
172 = SMARTMONTOOLS_ATTRIBUTELOG
188static bool warn_as_user;
189static uid_t warn_uid;
190static gid_t warn_gid;
191static std::string warn_uname, warn_gname;
194static bool warn_as_restr_user;
221static volatile int caughtsigUSR2=0;
232static void PrintOut(
int priority,
const char *
fmt, ...)
235#ifdef HAVE_LIBSYSTEMD
238static bool notify_enabled =
false;
242 if (!getenv(
"NOTIFY_SOCKET"))
244 notify_enabled =
true;
252 PrintOut(LOG_CRIT,
"Option -n (--no-fork) is required if 'Type=notify' is set.\n");
258static void notify_msg(
const char * msg,
bool ready =
false)
263 pout(
"sd_notify(0, \"%sSTATUS=%s\")\n", (ready ?
"READY=1\\n" :
""), msg);
266 sd_notifyf(0,
"%sSTATUS=%s", (ready ?
"READY=1\n" :
""), msg);
274 snprintf(msg,
sizeof(msg),
"Checking %d device%s ...",
275 numdev, (numdev != 1 ?
"s" :
""));
279static void notify_wait(time_t wakeuptime,
int numdev)
283 char ts[16] =
"";
struct tm tmbuf;
286 snprintf(msg,
sizeof(msg),
"Next check of %d device%s will start at %s",
287 numdev, (numdev != 1 ?
"s" :
""), ts);
288 static bool ready =
true;
299 case 0: msg =
"Exiting ...";
break;
300 case EXIT_BADCMD: msg =
"Error in command line (see SYSLOG)";
break;
302 case EXIT_READCONF: msg =
"Error in config file (see SYSLOG)";
break;
303 case EXIT_BADDEV: msg =
"Unable to register a device (see SYSLOG)";
break;
304 case EXIT_NODEV: msg =
"No devices to monitor";
break;
305 default: msg =
"Error (see SYSLOG)";
break;
316 if (getenv(
"NOTIFY_SOCKET")) {
317 PrintOut(LOG_CRIT,
"This version of smartd was build without 'Type=notify' support.\n");
347 bool is_set(
int id,
unsigned char flag)
const
348 {
return (0 <
id &&
id < (
int)
sizeof(
m_flags) && (
m_flags[
id] & flag)); }
352 if (0 <
id &&
id < (
int)
sizeof(
m_flags))
565 | ((uint64_t)ta.
raw[3] << 24)
566 | ((uint64_t)ta.
raw[4] << 32)
567 | ((uint64_t)ta.
raw[5] << 40);
581 memset(ta.
raw, 0,
sizeof(ta.
raw));
586 ta.
raw[0] = (
unsigned char) pa.
raw;
587 ta.
raw[1] = (
unsigned char)(pa.
raw >> 8);
588 ta.
raw[2] = (
unsigned char)(pa.
raw >> 16);
589 ta.
raw[3] = (
unsigned char)(pa.
raw >> 24);
590 ta.
raw[4] = (
unsigned char)(pa.
raw >> 32);
591 ta.
raw[5] = (
unsigned char)(pa.
raw >> 40);
603 "|(self-test-errors)"
604 "|(self-test-last-err-hour)"
605 "|(scheduled-test-next-check)"
606 "|(selective-test-last-start)"
607 "|(selective-test-last-end)"
609 "|(mail\\.([0-9]+)\\."
615 "|(ata-smart-attribute\\.([0-9]+)\\."
623 "|(nvme-err-log-entries)"
625 " *= *([0-9]+)[ \n]*$"
628 const int nmatch = 1+25;
632 if (
match[nmatch-1].rm_so < 0)
635 uint64_t val = strtoull(line +
match[nmatch-1].rm_so, (
char **)0, 10);
638 if (
match[++m].rm_so >= 0)
639 state.
tempmin = (
unsigned char)val;
640 else if (
match[++m].rm_so >= 0)
641 state.
tempmax = (
unsigned char)val;
642 else if (
match[++m].rm_so >= 0)
644 else if (
match[++m].rm_so >= 0)
646 else if (
match[++m].rm_so >= 0)
648 else if (
match[++m].rm_so >= 0)
650 else if (
match[++m].rm_so >= 0)
652 else if (
match[++m].rm_so >= 0)
654 else if (
match[m+=2].rm_so >= 0) {
655 int i = atoi(line+
match[m].rm_so);
660 if (
match[m+=2].rm_so >= 0)
662 else if (
match[++m].rm_so >= 0)
664 else if (
match[++m].rm_so >= 0)
669 else if (
match[m+=5+1].rm_so >= 0) {
670 int i = atoi(line+
match[m].rm_so);
673 if (
match[m+=2].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].rm_so >= 0)
686 else if (
match[m+7].rm_so >= 0)
699 pout(
"Cannot read state file \"%s\"\n", path);
703 setmode(fileno(f), O_TEXT);
707 int good = 0, bad = 0;
709 while (fgets(line,
sizeof(line), f)) {
710 const char *
s = line + strspn(line,
" \t");
711 if (!*
s || *
s ==
'#')
721 pout(
"%s: format error\n", path);
724 pout(
"%s: %d invalid line(s) ignored\n", path, bad);
735 fprintf(f,
"%s = %" PRIu64
"\n", name, val);
741 fprintf(f,
"%s.%d.%s = %" PRIu64
"\n", name1,
id, name2, val);
748 std::string pathbak = path; pathbak +=
'~';
749 unlink(pathbak.c_str());
750 rename(path, pathbak.c_str());
754 pout(
"Cannot create state file \"%s\"\n", path);
758 fprintf(f,
"# smartd state file\n");
803 pout(
"Cannot create attribute log file \"%s\"\n", path);
808 time_t now = time(
nullptr);
810 fprintf(f,
"%d-%02d-%02d %02d:%02d:%02d;",
811 1900+tms->tm_year, 1+tms->tm_mon, tms->tm_mday,
812 tms->tm_hour, tms->tm_min, tms->tm_sec);
817 fprintf(f,
"\t%d;%d;%" PRIu64
";", pa.id, pa.val, pa.raw);
821 const char * pageNames[3] = {
"read",
"write",
"verify"};
822 for (
int k = 0; k < 3; ++k) {
825 fprintf(f,
"\t%s-corr-by-ecc-fast;%" PRIu64
";"
826 "\t%s-corr-by-ecc-delayed;%" PRIu64
";"
827 "\t%s-corr-by-retry;%" PRIu64
";"
828 "\t%s-total-err-corrected;%" PRIu64
";"
829 "\t%s-corr-algorithm-invocations;%" PRIu64
";"
830 "\t%s-gb-processed;%.3f;"
831 "\t%s-total-unc-errors;%" PRIu64
";",
837 pageNames[k], (ecp->
counter[5] / 1000000000.0),
838 pageNames[k], ecp->
counter[6]);
845 fprintf(f,
"\ttemperature;%d;", state.
temperature);
855 bool write_always =
true)
857 for (
unsigned i = 0; i < states.size(); i++) {
868 PrintOut(LOG_INFO,
"Device: %s, state written to %s\n",
877 for (
unsigned i = 0; i < states.size(); i++) {
901static void USR2handler(
int sig)
932static int capabilities_mode ;
936 if (!capabilities_mode)
938 capng_clear(CAPNG_SELECT_BOTH);
939 capng_updatev(CAPNG_ADD, (capng_type_t)(CAPNG_EFFECTIVE|CAPNG_PERMITTED),
940 CAP_SYS_ADMIN, CAP_MKNOD, CAP_SYS_RAWIO, -1);
941 if (warn_as_user && (warn_uid || warn_gid)) {
943 capng_updatev(CAPNG_ADD, (capng_type_t)(CAPNG_EFFECTIVE|CAPNG_PERMITTED),
944 CAP_SETGID, CAP_SETUID, -1);
946 if (capabilities_mode > 1) {
948 capng_updatev(CAPNG_ADD, CAPNG_BOUNDING_SET,
949 CAP_SETGID, CAP_SETUID, CAP_CHOWN, CAP_FOWNER, CAP_DAC_OVERRIDE, -1);
951 capng_apply(CAPNG_SELECT_BOTH);
956 if (!capabilities_mode)
958 PrintOut(LOG_INFO,
"If mail notification does not work with '--capabilities%s\n",
959 (capabilities_mode == 1 ?
"', try '--capabilities=mail'"
960 :
"=mail', please inform " PACKAGE_BUGREPORT));
988 void set(
const char * name,
const char * value);
995 int size = strlen(name) + 1 + strlen(value) + 1;
996 char * newbuf =
new char[
size];
997 snprintf(newbuf,
size,
"%s=%s", name, value);
1000 throw std::runtime_error(
"putenv() failed");
1016 static const char *
const whichfail[] = {
1022 "FailedHealthCheck",
1023 "FailedReadSmartData",
1024 "FailedReadSmartErrorLog",
1025 "FailedReadSmartSelfTestLog",
1027 "CurrentPendingSector",
1028 "OfflineUncorrectableSector",
1044 PrintOut(LOG_CRIT,
"internal error in MailWarning(): cfg.mailwarn->emailfreq=%d\n",cfg.
emailfreq);
1048 PrintOut(LOG_CRIT,
"Contact " PACKAGE_BUGREPORT
"; internal error in MailWarning(): which=%d, size=%d\n",
1049 which, (
int)
sizeof(whichfail));
1058 if (which == 0 && mail->
logged)
1062 time_t epoch = time(
nullptr);
1065 const int day = 24*3600;
1071 int days = 0x01 << (mail->
logged - 1);
1094 std::replace(address.begin(), address.end(),
',',
' ');
1099 env[0].
set(
"SMARTD_MAILER", executable);
1100 env[1].
set(
"SMARTD_MESSAGE", message);
1102 snprintf(dates,
sizeof(dates),
"%d", mail->
logged);
1103 env[2].
set(
"SMARTD_PREVCNT", dates);
1105 env[3].
set(
"SMARTD_TFIRST", dates);
1107 env[4].
set(
"SMARTD_TFIRSTEPOCH", dates);
1108 env[5].
set(
"SMARTD_FAILTYPE", whichfail[which]);
1109 env[6].
set(
"SMARTD_ADDRESS", address.c_str());
1110 env[7].
set(
"SMARTD_DEVICESTRING", cfg.
name.c_str());
1113 env[8].
set(
"SMARTD_DEVICETYPE",
1115 env[9].
set(
"SMARTD_DEVICE", cfg.
dev_name.c_str());
1120 case 2: dates[0] =
'1'; dates[1] = 0;
break;
1121 case 3: snprintf(dates,
sizeof(dates),
"%d", (0x01)<<mail->
logged);
1123 env[11].
set(
"SMARTD_NEXTDAYS", dates);
1127 executable =
"<mail>";
1128 const char * newadd = (!address.empty()? address.c_str() :
"<nomailer>");
1129 const char * newwarn = (which?
"Warning via" :
"Test of");
1134 snprintf(command,
sizeof(command),
"\"%s\" 2>&1",
warning_script.c_str());
1136 snprintf(command,
sizeof(command),
"%s 2>&1",
warning_script.c_str());
1140 PrintOut(LOG_INFO,
"%s %s to %s%s ...\n",
1141 (which ?
"Sending warning via" :
"Executing test of"), executable, newadd,
1143#ifdef HAVE_POSIX_API
1146 (
unsigned)warn_uid, warn_uname.c_str(),
1147 (
unsigned)warn_gid, warn_gname.c_str() ).c_str() :
1149 warn_as_restr_user ?
" (restricted user)" :
1159#ifdef HAVE_POSIX_API
1166 pfp = popen_as_restr_user(command,
"r", warn_as_restr_user);
1168 pfp = popen(command,
"r");
1174 PrintOut(LOG_CRIT,
"%s %s to %s: failed (fork or pipe failed, or no memory) %s\n",
1175 newwarn, executable, newadd, errno?strerror(errno):
"");
1186 PrintOut(LOG_CRIT,
"%s %s to %s produced unexpected output (%s%d bytes) to STDOUT/STDERR: \n%s\n",
1187 newwarn, executable, newadd, len!=newlen?
"here truncated to ":
"", newlen,
buffer);
1195 PrintOut(LOG_CRIT,
"%s %s to %s: flushed remaining STDOUT/STDERR\n",
1196 newwarn, executable, newadd);
1198 PrintOut(LOG_CRIT,
"%s %s to %s: more than 1 MB STDOUT/STDERR flushed, breaking pipe\n",
1199 newwarn, executable, newadd);
1206#ifdef HAVE_POSIX_API
1212 status = pclose(pfp);
1216 PrintOut(LOG_CRIT,
"%s %s to %s: pclose(3) failed %s\n", newwarn, executable, newadd,
1217 errno?strerror(errno):
"");
1220 if (WIFEXITED(status)) {
1222 int status8 = WEXITSTATUS(status);
1224 PrintOut(LOG_CRIT,
"%s %s to %s: failed (32-bit/8-bit exit status: %d/%d) perhaps caught signal %d [%s]\n",
1225 newwarn, executable, newadd, status, status8, status8-128, strsignal(status8-128));
1227 PrintOut(LOG_CRIT,
"%s %s to %s: failed (32-bit/8-bit exit status: %d/%d)\n",
1228 newwarn, executable, newadd, status, status8);
1232 PrintOut(LOG_INFO,
"%s %s to %s: successful\n", newwarn, executable, newadd);
1235 if (WIFSIGNALED(status))
1236 PrintOut(LOG_INFO,
"%s %s to %s: exited because of uncaught signal %d [%s]\n",
1237 newwarn, executable, newadd, WTERMSIG(status), strsignal(WTERMSIG(status)));
1241 if (WIFSTOPPED(status))
1242 PrintOut(LOG_CRIT,
"%s %s to %s: process STOPPED because it caught signal %d [%s]\n",
1243 newwarn, executable, newadd, WSTOPSIG(status), strsignal(WSTOPSIG(status)));
1272 PrintOut(LOG_INFO,
"Device: %s, %s, warning condition reset after %d email%s\n", cfg.
name.c_str(),
1284static
void vsyslog_lines(
int priority, const
char *
fmt, va_list
ap)
1289 for (
char * p = buf, * q; p && *p; p = q) {
1290 if ((q = strchr(p,
'\n')))
1293 syslog(priority,
"%s\n", p);
1299#define vsyslog_lines vsyslog
1323 vfprintf(f,
fmt,
ap);
1328 openlog(
"smartd", LOG_PID,
facility);
1329 vsyslog_lines(LOG_INFO,
fmt,
ap);
1350 vfprintf(f,
fmt,
ap);
1354 openlog(
"smartd", LOG_PID,
facility);
1355 vsyslog_lines(priority,
fmt,
ap);
1365 pout(
"Warning! %s error: invalid SMART checksum.\n",
string);
1374 int waited, max_wait = 10;
1375 struct stat stat_buf;
1380 for(waited = 0; waited < max_wait; ++waited) {
1381 if (!stat(
pid_file.c_str(), &stat_buf)) {
1405 if ((pid=fork()) < 0) {
1407 PrintOut(LOG_CRIT,
"smartd unable to fork daemon process!\n");
1423 if ((pid=fork()) < 0) {
1425 PrintOut(LOG_CRIT,
"smartd unable to fork daemon process!\n");
1436 for (
int i = getdtablesize(); --i >= 0; )
1440 int fd = open(
"/dev/null", O_RDWR);
1441 if (!(fd == 0 && dup(fd) == 1 && dup(fd) == 2 && !chdir(
"/"))) {
1442 PrintOut(LOG_CRIT,
"smartd unable to redirect to /dev/null or to chdir to root!\n");
1448 PrintOut(LOG_INFO,
"smartd has fork()ed into background mode. New PID=%d.\n", (
int)getpid());
1455 if (daemon_detach(
"smartd")) {
1456 PrintOut(LOG_CRIT,
"smartd unable to detach from console!\n");
1471 pid_t pid = getpid();
1474 old_umask = umask(0077);
1477 old_umask = umask(0033);
1482 if (!(f && fprintf(f,
"%d\n", (
int)pid) > 0 && f.
close())) {
1483 PrintOut(LOG_CRIT,
"unable to write PID file %s - exiting.\n",
pid_file.c_str());
1486 PrintOut(LOG_INFO,
"file %s written containing PID %d\n",
pid_file.c_str(), (
int)pid);
1501 "Configuration file (%s) Directives (after device name):\n"
1502 " -d TYPE Set the device type: auto, ignore, removable,\n"
1504 " -T TYPE Set the tolerance to one of: normal, permissive\n"
1505 " -o VAL Enable/disable automatic offline tests (on/off)\n"
1506 " -S VAL Enable/disable attribute autosave (on/off)\n"
1507 " -n MODE No check if: never, sleep[,N][,q], standby[,N][,q], idle[,N][,q]\n"
1508 " -H Monitor SMART Health Status, report if failed\n"
1509 " -s REG Do Self-Test at time(s) given by regular expression REG\n"
1510 " -l TYPE Monitor SMART log or self-test status:\n"
1511 " error, selftest, xerror, offlinests[,ns], selfteststs[,ns]\n"
1512 " -l scterc,R,W Set SCT Error Recovery Control\n"
1513 " -e Change device setting: aam,[N|off], apm,[N|off], dsn,[on|off],\n"
1514 " lookahead,[on|off], security-freeze, standby,[N|off], wcache,[on|off]\n"
1515 " -f Monitor 'Usage' Attributes, report failures\n"
1516 " -m ADD Send email warning to address ADD\n"
1517 " -M TYPE Modify email warning behavior (see man page)\n"
1518 " -p Report changes in 'Prefailure' Attributes\n"
1519 " -u Report changes in 'Usage' Attributes\n"
1520 " -t Equivalent to -p and -u Directives\n"
1521 " -r ID Also report Raw values of Attribute ID with -p, -u or -t\n"
1522 " -R ID Track changes in Attribute ID Raw value with -p, -u or -t\n"
1523 " -i ID Ignore Attribute ID for -f Directive\n"
1524 " -I ID Ignore Attribute ID for -p, -u or -t Directive\n"
1525 " -C ID[+] Monitor [increases of] Current Pending Sectors in Attribute ID\n"
1526 " -U ID[+] Monitor [increases of] Offline Uncorrectable Sectors in Attribute ID\n"
1527 " -W D,I,C Monitor Temperature D)ifference, I)nformal limit, C)ritical limit\n"
1528 " -v N,ST Modifies labeling of Attribute N (see man page) \n"
1529 " -P TYPE Drive-specific presets: use, ignore, show, showall\n"
1530 " -a Default: -H -f -t -l error -l selftest -l selfteststs -C 197 -U 198\n"
1531 " -F TYPE Use firmware bug workaround:\n"
1533 " -c i=N Set interval between disk checks to N seconds\n"
1534 " # Comment: text after a hash sign is ignored\n"
1535 " \\ Line continuation character\n"
1536 "Attribute ID is a decimal integer 1 <= ID <= 255\n"
1537 "Use ID = 0 to turn off -C and/or -U Directives\n"
1538 "Example: /dev/sda -a\n",
1540 smi()->get_valid_dev_types_str().c_str(),
1551 return "<PATH_PREFIX>, -";
1553 return "[+]<FILE_NAME>";
1555 return "<FILE_NAME>, -";
1557 return "daemon, local0, local1, local2, local3, local4, local5, local6, local7";
1559 return "nodev[0], errors[,nodev0], nodev[0]startup, never, onecheck, showtests";
1561 return "ioctl[,N], ataioctl[,N], scsiioctl[,N], nvmeioctl[,N]";
1564 return "<FILE_NAME>";
1566 return "<INTEGER_SECONDS>";
1567#ifdef HAVE_POSIX_API
1569 return "<USER>[:<GROUP>], -";
1570#elif defined(_WIN32)
1572 return "restricted, unchanged";
1574#ifdef HAVE_LIBCAP_NG
1576 return "mail, <no_argument>";
1586 PrintOut(LOG_INFO,
"Usage: smartd [options]\n\n");
1587#ifdef SMARTMONTOOLS_ATTRIBUTELOG
1588 PrintOut(LOG_INFO,
" -A PREFIX|-, --attributelog=PREFIX|-\n");
1590 PrintOut(LOG_INFO,
" -A PREFIX, --attributelog=PREFIX\n");
1592 PrintOut(LOG_INFO,
" Log attribute information to {PREFIX}MODEL-SERIAL.TYPE.csv\n");
1593#ifdef SMARTMONTOOLS_ATTRIBUTELOG
1594 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_ATTRIBUTELOG
"MODEL-SERIAL.TYPE.csv]\n");
1597 PrintOut(LOG_INFO,
" -B [+]FILE, --drivedb=[+]FILE\n");
1598 PrintOut(LOG_INFO,
" Read and replace [add] drive database from FILE\n");
1600#ifdef SMARTMONTOOLS_DRIVEDBDIR
1602 PrintOut(LOG_INFO,
" and then %s", get_drivedb_path_default());
1605 PrintOut(LOG_INFO,
" -c NAME|-, --configfile=NAME|-\n");
1606 PrintOut(LOG_INFO,
" Read configuration file NAME or stdin\n");
1608#ifdef HAVE_LIBCAP_NG
1609 PrintOut(LOG_INFO,
" -C, --capabilities[=mail]\n");
1610 PrintOut(LOG_INFO,
" Drop unneeded Linux process capabilities.\n"
1611 " Warning: Mail notification may not work when used.\n\n");
1613 PrintOut(LOG_INFO,
" -d, --debug\n");
1614 PrintOut(LOG_INFO,
" Start smartd in debug mode\n\n");
1615 PrintOut(LOG_INFO,
" -D, --showdirectives\n");
1616 PrintOut(LOG_INFO,
" Print the configuration file Directives and exit\n\n");
1617 PrintOut(LOG_INFO,
" -h, --help, --usage\n");
1618 PrintOut(LOG_INFO,
" Display this help and exit\n\n");
1619 PrintOut(LOG_INFO,
" -i N, --interval=N\n");
1620 PrintOut(LOG_INFO,
" Set interval between disk checks to N seconds, where N >= 10\n\n");
1621 PrintOut(LOG_INFO,
" -l local[0-7], --logfacility=local[0-7]\n");
1623 PrintOut(LOG_INFO,
" Use syslog facility local0 - local7 or daemon [default]\n\n");
1625 PrintOut(LOG_INFO,
" Log to \"./smartd.log\", stdout, stderr [default is event log]\n\n");
1628 PrintOut(LOG_INFO,
" -n, --no-fork\n");
1629 PrintOut(LOG_INFO,
" Do not fork into background\n");
1630#ifdef HAVE_LIBSYSTEMD
1631 PrintOut(LOG_INFO,
" (systemd 'Type=notify' is assumed if $NOTIFY_SOCKET is set)\n");
1635 PrintOut(LOG_INFO,
" -p NAME, --pidfile=NAME\n");
1636 PrintOut(LOG_INFO,
" Write PID file NAME\n\n");
1637 PrintOut(LOG_INFO,
" -q WHEN, --quit=WHEN\n");
1639 PrintOut(LOG_INFO,
" -r, --report=TYPE\n");
1641#ifdef SMARTMONTOOLS_SAVESTATES
1642 PrintOut(LOG_INFO,
" -s PREFIX|-, --savestates=PREFIX|-\n");
1644 PrintOut(LOG_INFO,
" -s PREFIX, --savestates=PREFIX\n");
1646 PrintOut(LOG_INFO,
" Save disk states to {PREFIX}MODEL-SERIAL.TYPE.state\n");
1647#ifdef SMARTMONTOOLS_SAVESTATES
1648 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_SAVESTATES
"MODEL-SERIAL.TYPE.state]\n");
1651 PrintOut(LOG_INFO,
" -w NAME, --warnexec=NAME\n");
1652 PrintOut(LOG_INFO,
" Run executable NAME on warnings\n");
1654 PrintOut(LOG_INFO,
" [default is " SMARTMONTOOLS_SMARTDSCRIPTDIR
"/smartd_warning.sh]\n\n");
1658#ifdef HAVE_POSIX_API
1659 PrintOut(LOG_INFO,
" -u USER[:GROUP], --warn-as-user=USER[:GROUP]\n");
1660 PrintOut(LOG_INFO,
" Run warning script as non-privileged USER\n\n");
1661#elif defined(_WIN32)
1662 PrintOut(LOG_INFO,
" -u MODE, --warn-as-user=MODE\n");
1667 PrintOut(LOG_INFO,
" Running as windows service (see man page), install with:\n");
1668 PrintOut(LOG_INFO,
" smartd install [options]\n");
1669 PrintOut(LOG_INFO,
" Remove service with:\n");
1670 PrintOut(LOG_INFO,
" smartd remove\n\n");
1672 PrintOut(LOG_INFO,
" -V, --version, --license, --copyright\n");
1673 PrintOut(LOG_INFO,
" Print License, Copyright, and version information\n");
1678 if (!device->
close()){
1689 bool changed =
false;
1690 for (
unsigned i = 0; i <
s.size(); i++) {
1694 if ((
' ' <= c && c <=
'~') && !(i == 0 && c ==
'~'))
1705 return !( (
'0' <= c && c <=
'9')
1706 || (
'A' <= c && c <=
'Z')
1707 || (
'a' <= c && c <=
'z'));
1718 PrintOut(LOG_INFO,
"Device: %s, Read Summary SMART Error Log failed\n",name);
1726 PrintOut(LOG_INFO,
"Device: %s, Read Extended Comprehensive SMART Error Log failed\n",name);
1742 PrintOut(LOG_INFO,
"Device: %s, Read SMART Self Test Log Failed\n",name);
1751 int errcnt = 0, hours = 0;
1752 for (
int i = 20; i >= 0; i--) {
1758 int status =
entry.selfteststatus >> 4;
1759 if (status == 0x0 && (
entry.selftestnumber & 0x7f) == 0x02)
1763 if (0x3 <= status && status <= 0x8) {
1768 hours =
entry.timestamp;
1772 return ((hours << 8) | errcnt);
1775#define SELFTEST_ERRORCOUNT(x) (x & 0xff)
1776#define SELFTEST_ERRORHOURS(x) ((x >> 8) & 0xffff)
1781 return ((status & 0x7f) == 0x03);
1787 return ((status >> 4) == 0xf);
1794 switch (status & 0x7f) {
1795 case 0x00: msg =
"was never started";
break;
1796 case 0x02: msg =
"was completed without error";
break;
1797 case 0x03: msg =
"is in progress";
break;
1798 case 0x04: msg =
"was suspended by an interrupting command from host";
break;
1799 case 0x05: msg =
"was aborted by an interrupting command from host";
break;
1800 case 0x06: msg =
"was aborted by the device with a fatal error";
break;
1801 default: msg =
nullptr;
1805 PrintOut(((status & 0x7f) == 0x06 ? LOG_CRIT : LOG_INFO),
1806 "Device: %s, offline data collection %s%s\n", name, msg,
1807 ((status & 0x80) ?
" (auto:on)" :
""));
1809 PrintOut(LOG_INFO,
"Device: %s, unknown offline data collection status 0x%02x\n",
1817 switch (status >> 4) {
1818 case 0x0: msg =
"completed without error";
break;
1819 case 0x1: msg =
"was aborted by the host";
break;
1820 case 0x2: msg =
"was interrupted by the host with a reset";
break;
1821 case 0x3: msg =
"could not complete due to a fatal or unknown error";
break;
1822 case 0x4: msg =
"completed with error (unknown test element)";
break;
1823 case 0x5: msg =
"completed with error (electrical test element)";
break;
1824 case 0x6: msg =
"completed with error (servo/seek test element)";
break;
1825 case 0x7: msg =
"completed with error (read test element)";
break;
1826 case 0x8: msg =
"completed with error (handling damage?)";
break;
1827 default: msg =
nullptr;
1831 PrintOut(((status >> 4) >= 0x4 ? LOG_CRIT : LOG_INFO),
1832 "Device: %s, previous self-test %s\n", name, msg);
1833 else if ((status >> 4) == 0xf)
1834 PrintOut(LOG_INFO,
"Device: %s, self-test in progress, %u0%% remaining\n",
1835 name, status & 0x0f);
1837 PrintOut(LOG_INFO,
"Device: %s, unknown self-test status 0x%02x\n",
1843 unsigned char id,
const char * msg)
1848 PrintOut(LOG_INFO,
"Device: %s, can't monitor %s count - no Attribute %d\n",
1849 cfg.
name.c_str(), msg,
id);
1857 PrintOut(LOG_INFO,
"Device: %s, ignoring %s count - bogus Attribute %d value %" PRIu64
" (0x%" PRIx64
")\n",
1858 cfg.
name.c_str(), msg,
id, rawval, rawval);
1884 int set_option = 0,
bool has_value =
false)
1891 else if (set_option < 0)
1895 else if (set_option > 0)
1905 for (
const auto & prev_cfg : prev_cfgs) {
1906 if (!prev_cfg.id_is_unique)
1911 PrintOut(LOG_INFO,
"Device: %s, same identity as %s, ignored\n",
1912 cfg.
dev_name.c_str(), prev_cfg.dev_name.c_str());
1928 const char *name = cfg.
name.c_str();
1937 PrintOut(LOG_INFO,
"Device: %s, not ATA, no IDENTIFY DEVICE Structure\n",name);
1939 PrintOut(LOG_INFO,
"Device: %s, packet devices [this device %s] not SMART capable\n",
1946 char model[40+1], serial[20+1], firmware[8+1];
1956 char wwn[64]; wwn[0] = 0;
1957 unsigned oui = 0; uint64_t unique_id = 0;
1960 snprintf(wwn,
sizeof(wwn),
"WWN:%x-%06x-%09" PRIx64
", ", naa, oui, unique_id);
1981 PrintOut(LOG_INFO,
"Device: %s, smartd database not searched (Directive: -P ignore).\n", name);
1984 std::string dbversion;
1988 PrintOut(LOG_INFO,
"Device: %s, not found in smartd database%s%s.\n", name,
1989 (!dbversion.empty() ?
" " :
""), (!dbversion.empty() ? dbversion.c_str() :
""));
1991 PrintOut(LOG_INFO,
"Device: %s, found in smartd database%s%s%s%s\n",
1992 name, (!dbversion.empty() ?
" " :
""), (!dbversion.empty() ? dbversion.c_str() :
""),
2001 bool locked = ((word128 & 0x0007) == 0x0007);
2003 PrintOut(LOG_INFO,
"Device: %s, ATA Security is **LOCKED**\n", name);
2015 PrintOut(LOG_INFO,
"Device %s: presets are:\n", name);
2027 PrintOut(LOG_INFO,
"Device: %s, lacks SMART capability\n",name);
2030 PrintOut(LOG_INFO,
"Device: %s, ATA IDENTIFY DEVICE words 82-83 don't specify if SMART capable.\n",name);
2034 PrintOut(LOG_INFO,
"Device: %s, proceeding since '-T permissive' Directive given.\n",name);
2037 PrintOut(LOG_INFO,
"Device: %s, to proceed anyway, use '-T permissive' Directive.\n",name);
2045 PrintOut(LOG_INFO,
"Device: %s, could not enable SMART capability\n",name);
2049 PrintOut(LOG_INFO,
"Device: %s, to proceed anyway, use '-T permissive' Directive.\n", name);
2053 PrintOut(LOG_INFO,
"Device: %s, proceeding since '-T permissive' Directive given.\n", name);
2056 PrintOut(LOG_INFO,
"Device: %s, proceeding since SMART is already enabled\n", name);
2063 PrintOut(LOG_INFO,
"Device: %s, could not disable SMART Attribute Autosave.\n",name);
2065 PrintOut(LOG_INFO,
"Device: %s, disabled SMART Attribute Autosave.\n",name);
2071 PrintOut(LOG_INFO,
"Device: %s, could not enable SMART Attribute Autosave.\n",name);
2073 PrintOut(LOG_INFO,
"Device: %s, enabled SMART Attribute Autosave.\n",name);
2078 PrintOut(LOG_INFO,
"Device: %s, not capable of SMART Health Status check\n",name);
2089 bool smart_val_ok =
false;
2098 PrintOut(LOG_INFO,
"Device: %s, Read SMART Values failed\n", name);
2104 smart_val_ok =
true;
2106 PrintOut(LOG_INFO,
"Device: %s, Read SMART Thresholds failed%s\n",
2107 name, (cfg.
usagefailed ?
", ignoring -f Directive" :
""));
2118 "Current_Pending_Sector"))
2123 "Offline_Uncorrectable"))
2128 PrintOut(LOG_INFO,
"Device: %s, can't monitor Temperature, ignoring -W %d,%d,%d\n",
2134 for (
int id = 1;
id <= 255;
id++) {
2142 PrintOut(LOG_INFO,
"Device: %s, no Attribute %d, ignoring -%c %d%s\n", name,
id, opt,
id, excl);
2145 if (!((prefail && cfg.
prefail) || (!prefail && cfg.
usage)))
2146 PrintOut(LOG_INFO,
"Device: %s, not monitoring %s Attributes, ignoring -%c %d%s\n", name,
2147 (prefail ?
"Prefailure" :
"Usage"), opt,
id, excl);
2158 PrintOut(LOG_INFO,
"Device: %s, could not %s SMART Automatic Offline Testing.\n",name, what);
2162 PrintOut(LOG_INFO,
"Device: %s, SMART Automatic Offline Testing unsupported...\n",name);
2165 PrintOut(LOG_INFO,
"Device: %s, %s SMART Automatic Offline Testing failed.\n", name, what);
2167 PrintOut(LOG_INFO,
"Device: %s, %sd SMART Automatic Offline Testing.\n", name, what);
2173 bool smart_logdir_ok =
false, gp_logdir_ok =
false;
2179 smart_logdir_ok =
true;
2184 gp_logdir_ok =
true;
2194 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test Log, ignoring -l selftest (override with -T permissive)\n", name);
2198 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test Log, ignoring -l selftest\n", name);
2214 PrintOut(LOG_INFO,
"Device: %s, no SMART Error Log, ignoring -l error (override with -T permissive)\n", name);
2218 PrintOut(LOG_INFO,
"Device: %s, no SMART Error Log, ignoring -l error\n", name);
2229 PrintOut(LOG_INFO,
"Device: %s, no Extended Comprehensive SMART Error Log, ignoring -l xerror (override with -T permissive)\n",
2234 PrintOut(LOG_INFO,
"Device: %s, no Extended Comprehensive SMART Error Log, ignoring -l xerror\n", name);
2238 PrintOut(LOG_INFO,
"Device: %s, SMART Error Logs report different error counts: %d != %d\n",
2252 PrintOut(LOG_INFO,
"Device: %s, no SMART Offline Data Collection capability, ignoring -l offlinests (override with -T permissive)\n", name);
2254 PrintOut(LOG_INFO,
"Device: %s, no SMART Self-test capability, ignoring -l selfteststs (override with -T permissive)\n", name);
2263 if (-1 == powermode) {
2264 PrintOut(LOG_CRIT,
"Device: %s, no ATA CHECK POWER STATUS support, ignoring -n Directive\n", name);
2267 else if (powermode!=0x00 && powermode!=0x01
2268 && powermode!=0x40 && powermode!=0x41
2269 && powermode!=0x80 && powermode!=0x81 && powermode!=0x82 && powermode!=0x83
2270 && powermode!=0xff) {
2271 PrintOut(LOG_CRIT,
"Device: %s, CHECK POWER STATUS returned %d, not ATA compliant, ignoring -n Directive\n",
2313 PrintOut(LOG_INFO,
"Device: %s, ATA settings applied: %s\n", name, msg.c_str());
2318 PrintOut(LOG_INFO,
"Device: %s, no SCT Error Recovery Control support, ignoring -l scterc\n",
2321 PrintOut(LOG_INFO,
"Device: %s, no SCT support if ATA Security is LOCKED, ignoring -l scterc\n",
2325 PrintOut(LOG_INFO,
"Device: %s, set of SCT Error Recovery Control failed\n", name);
2327 PrintOut(LOG_INFO,
"Device: %s, SCT Error Recovery Control set to: Read: %u, Write: %u\n",
2342 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n",name);
2355 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", name, cfg.
state_file.c_str());
2374 int err, req_len, avail_len, version, len;
2375 const char *device = cfg.
name.c_str();
2379 uint8_t vpdBuf[252];
2380 char lu_id[64], serial[256], vendor[40], model[40];
2383 memset(inqBuf, 0, 96);
2389 PrintOut(LOG_INFO,
"Device: %s, Both 36 and 64 byte INQUIRY failed; "
2390 "skip device\n", device);
2394 version = (inqBuf[2] & 0x7f);
2396 avail_len = inqBuf[4] + 5;
2397 len = (avail_len < req_len) ? avail_len : req_len;
2399 PrintOut(LOG_INFO,
"Device: %s, INQUIRY response less than 36 bytes; "
2400 "skip device\n", device);
2404 int pdt = inqBuf[0] & 0x1f;
2406 if (! ((0 == pdt) || (4 == pdt) || (5 == pdt) || (7 == pdt) ||
2408 PrintOut(LOG_INFO,
"Device: %s, not a disk like device [PDT=0x%x], "
2409 "skip\n", device, pdt);
2420 if ((version >= 0x3) && (version < 0x8)) {
2423 vpdBuf,
sizeof(vpdBuf))) {
2430 vpdBuf,
sizeof(vpdBuf))) {
2432 vpdBuf[4 + len] =
'\0';
2447 (
char *)&inqBuf[8], (
char *)&inqBuf[16], (
char *)&inqBuf[32],
2448 (lu_id[0] ?
", lu id: " :
""), (lu_id[0] ? lu_id :
""),
2449 (serial[0] ?
", S/N: " :
""), (serial[0] ? serial :
""),
2450 (si_str[0] ?
", " :
""), (si_str[0] ? si_str :
""));
2470 PrintOut(LOG_INFO,
"Device: %s, NOT READY (e.g. spun down); skip device\n", device);
2472 PrintOut(LOG_INFO,
"Device: %s, NO MEDIUM present; skip device\n", device);
2474 PrintOut(LOG_INFO,
"Device: %s, BECOMING (but not yet) READY; skip device\n", device);
2476 PrintOut(LOG_CRIT,
"Device: %s, failed Test Unit Ready [err=%d]\n", device, err);
2493 "Device: %s, Bad IEC (SMART) mode page, err=%d, skip device\n",
2502 PrintOut(LOG_INFO,
"Device: %s, IE (SMART) not enabled, skip device\n"
2503 "Try 'smartctl -s on %s' to turn on SMART features\n",
2545 uint8_t currenttemp = 0;
2546 uint8_t triptemp = 0;
2549 &asc, &ascq, ¤ttemp, &triptemp)) {
2550 PrintOut(LOG_INFO,
"Device: %s, unexpectedly failed to read SMART values\n", device);
2555 PrintOut(LOG_INFO,
"Device: %s, can't monitor Temperature, ignoring -W %d,%d,%d\n",
2566 PrintOut(LOG_INFO,
"Device: %s, does not support SMART Self-Test Log.\n", device);
2581 PrintOut(LOG_INFO,
"Device: %s, could not disable autosave (set GLTSD bit).\n",device);
2583 PrintOut(LOG_INFO,
"Device: %s, disabled autosave (set GLTSD bit).\n",device);
2589 PrintOut(LOG_INFO,
"Device: %s, could not enable autosave (clear GLTSD bit).\n",device);
2591 PrintOut(LOG_INFO,
"Device: %s, enabled autosave (cleared GLTSD bit).\n",device);
2595 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n", device);
2611 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", device, cfg.
state_file.c_str());
2628 for (
int i = 8; i < 16; i++) {
2630 return ~(uint64_t)0;
2632 uint64_t lo = val[7];
2633 for (
int i = 7-1; i >= 0; i--) {
2634 lo <<= 8; lo += val[i];
2653 const char *name = cfg.
name.c_str();
2660 PrintOut(LOG_INFO,
"Device: %s, NVMe Identify Controller failed\n", name);
2666 char model[40+1], serial[20+1], firmware[8+1];
2672 char nsstr[32] =
"", capstr[32] =
"";
2674 if (
nsid != 0xffffffff)
2675 snprintf(nsstr,
sizeof(nsstr),
", NSID:%u",
nsid);
2680 nsstr, (capstr[0] ?
", " :
""), capstr);
2696 PrintOut(LOG_INFO,
"Device: %s, failed to read NVMe SMART/Health Information\n", name);
2704 PrintOut(LOG_INFO,
"Device: %s, no Temperature sensors, ignoring -W %d,%d,%d\n",
2723 PrintOut(LOG_INFO,
"Device: %s, is SMART capable. Adding to \"monitor\" list.\n", name);
2735 if (
nsid != 0xffffffff)
2736 snprintf(nsstr,
sizeof(nsstr),
"-n%u",
nsid);
2740 PrintOut(LOG_INFO,
"Device: %s, state read from %s\n", name, cfg.
state_file.c_str());
2752 const char * name = cfg.
name.c_str();
2756 MailWarning(cfg, state, 0,
"TEST EMAIL from smartd for device: %s", name);
2771 PrintOut(LOG_INFO,
"Device: %s, is in %s mode, suspending checks\n", name,
"STANDBY (OS)");
2782 if (!device->
open()) {
2785 PrintOut(LOG_INFO,
"Device: %s, open() of %s device failed: %s\n", name, type, device->
get_errmsg());
2786 MailWarning(cfg, state, 9,
"Device: %s, unable to open %s device", name, type);
2789 PrintOut(LOG_INFO,
"Device: %s, removed %s device: %s\n", name, type, device->
get_errmsg());
2793 PrintOut(LOG_INFO,
"Device: %s, %s device still removed: %s\n", name, type, device->
get_errmsg());
2798 PrintOut(LOG_INFO,
"Device: %s, opened %s device\n", name, type);
2803 PrintOut(LOG_INFO,
"Device: %s, reconnected %s device\n", name, type);
2814 const char * name = cfg.
name.c_str();
2818 MailWarning(cfg, state, 8,
"Device: %s, Read SMART Self-Test Log Failed", name);
2832 PrintOut(LOG_CRIT,
"Device: %s, Self-Test Log error count increased from %d to %d\n",
2834 MailWarning(cfg, state, 3,
"Device: %s, Self-Test Log error count increased from %d to %d",
2838 else if (newc > 0 && oldh != newh) {
2846 PrintOut(LOG_CRIT,
"Device: %s, new Self-Test Log error at hour timestamp %d\n",
2848 MailWarning(cfg, state, 3,
"Device: %s, new Self-Test Log error at hour timestamp %d",
2856 PrintOut(LOG_INFO,
"Device: %s, Self-Test Log error count decreased from %d to %d\n",
2893 time_t now = (!usetime ? time(
nullptr) : usetime);
2907 unsigned offsets[max_offsets] = {0, }, limits[max_offsets] = {0, };
2908 unsigned num_offsets = 1;
2910 const char * q = strchr(p,
':');
2914 unsigned offset = 0, limit = 0;
int n1 = -1, n2 = -1, n3 = -1;
2915 sscanf(p,
"%u%n-%n%u%n", &offset, &n1, &n2, &limit, &n3);
2916 if (!(n1 == 3 && (n2 < 0 || (n3 == 3+1+3 && limit > 0))))
2918 offsets[num_offsets] = offset; limits[num_offsets] = limit;
2920 p += (n3 > 0 ? n3 : n1);
2925 time_t testtime = 0;
int testhour = 0;
2930 for (
unsigned i = 0; i < num_offsets; i++) {
2931 unsigned offset = offsets[i], limit = limits[i];
2933 if (0 < limit && limit < delay)
2938 int weekday = (tms->tm_wday ? tms->tm_wday : 7);
2939 for (
int j = 0; j <= maxtest; j++) {
2952 snprintf(pattern,
sizeof(pattern),
"%c/%02d/%02d/%1d/%02d",
2953 test_type_chars[j], tms->tm_mon+1, tms->tm_mday, weekday, tms->tm_hour);
2955 const unsigned len =
sizeof(
"S/01/01/1/01") - 1;
2956 snprintf(pattern + len,
sizeof(pattern) - len,
":%03u", offset);
2958 snprintf(pattern + len + 4,
sizeof(pattern) - len - 4,
"-%03u", limit);
2962 testtype = pattern[0];
2963 testtime = t; testhour = tms->tm_hour;
2977 if ((t += 3600) > now)
2988 if (!usetime && !(testhour == tmnow->tm_hour && testtime + 3600 > now)) {
2990 PrintOut(LOG_INFO,
"Device: %s, old test of type %c not run at %s, starting now.\n",
2991 cfg.
name.c_str(), testtype, datebuf);
3001 unsigned numdev = configs.size();
3006 PrintOut(LOG_INFO,
"\nNext scheduled self tests (at most 5 of each type per device):\n");
3009 time_t now = time(
nullptr);
3016 time_t testtime = now + seconds;
3017 for (
unsigned i = 0; i < numdev; i++) {
3027 PrintOut(LOG_INFO,
"Device: %s, will do test %d of type %c at %s\n", cfg.
name.c_str(),
3036 PrintOut(LOG_INFO,
"\nTotals [%s - %s]:\n", datenow, date);
3037 for (
unsigned i = 0; i < numdev; i++) {
3039 bool scsi =
devices.at(i)->is_scsi();
3044 PrintOut(LOG_INFO,
"Device: %s, will do %3d test%s of type %c\n", cfg.
name.c_str(),
3056 const char *testname =
nullptr;
3057 const char *name = cfg.
name.c_str();
3061 PrintOut(LOG_CRIT,
"Device: %s, does not support Self-Tests\n", name);
3066 if (1 == inProgress) {
3067 PrintOut(LOG_INFO,
"Device: %s, skip since Self-Test already in "
3068 "progress.\n", name);
3074 testname =
"Short Self";
3078 testname =
"Long Self";
3084 PrintOut(LOG_CRIT,
"Device: %s, not capable of %c Self-Test\n", name,
3091 PrintOut(LOG_CRIT,
"Device: %s, not capable of %s-Test\n", name,
3100 PrintOut(LOG_CRIT,
"Device: %s, execute %s-Test failed (err: %d)\n", name,
3105 PrintOut(LOG_INFO,
"Device: %s, starting scheduled %s-Test.\n", name, testname);
3114 const char *name = cfg.
name.c_str();
3119 PrintOut(LOG_CRIT,
"Device: %s, not capable of Offline or Self-Testing.\n", name);
3124 int dotest = -1, mode = 0;
3125 const char *testname =
nullptr;
3128 testname=
"Offline Immediate ";
3135 testname=
"Conveyance Self-";
3142 testname=
"Short Self-";
3149 testname=
"Long Self-";
3156 case 'c':
case 'n':
case 'r':
3157 testname =
"Selective Self-";
3173 PrintOut(LOG_CRIT,
"Device: %s, not capable of %sTest\n", name, testname);
3178 if (15==(
data.self_test_exec_status >> 4)) {
3180 PrintOut(LOG_INFO,
"Device: %s, will not skip scheduled %sTest "
3181 "despite unclear Self-Test byte (SAMSUNG Firmware bug).\n", name, testname);
3183 PrintOut(LOG_INFO,
"Device: %s, skip scheduled %sTest; %1d0%% remaining of current Self-Test.\n",
3184 name, testname, (
int)(
data.self_test_exec_status & 0x0f));
3198 PrintOut(LOG_CRIT,
"Device: %s, prepare %sTest failed\n", name, testname);
3202 PrintOut(LOG_INFO,
"Device: %s, %s test span at LBA %" PRIu64
" - %" PRIu64
" (%" PRIu64
" sectors, %u%% - %u%% of disk).\n",
3204 start, end, end - start + 1,
3214 PrintOut(LOG_CRIT,
"Device: %s, execute %sTest failed.\n", name, testname);
3220 if (testtype ==
'O')
3225 PrintOut(LOG_INFO,
"Device: %s, starting scheduled %sTest.\n", name, testname);
3231 unsigned char id,
bool increase_only,
3233 int mailtype,
const char * msg)
3249 if (!(!increase_only || prev_rawval < rawval))
3253 std::string
s =
strprintf(
"Device: %s, %" PRId64
" %s", cfg.
name.c_str(), rawval, msg);
3254 if (prev_rawval > 0 && rawval != prev_rawval)
3255 s +=
strprintf(
" (changed %+" PRId64
")", rawval - prev_rawval);
3263static const char *
fmt_temp(
unsigned char x,
char (& buf)[20])
3267 snprintf(buf,
sizeof(buf),
"%u", x);
3274 if (!(0 < currtemp && currtemp < 255)) {
3275 PrintOut(LOG_INFO,
"Device: %s, failed to read Temperature\n", cfg.
name.c_str());
3280 const char * minchg =
"", * maxchg =
"";
3281 if (currtemp > state.
tempmax) {
3294 PrintOut(LOG_INFO,
"Device: %s, initial Temperature is %d Celsius (Min/Max %s/%u%s)\n",
3297 PrintOut(LOG_INFO,
" [trip Temperature is %d Celsius]\n", (
int)triptemp);
3321 PrintOut(LOG_INFO,
"Device: %s, Temperature changed %+d Celsius to %u Celsius (Min/Max %s%s/%u%s)\n",
3329 PrintOut(LOG_CRIT,
"Device: %s, Temperature %u Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)\n",
3331 MailWarning(cfg, state, 12,
"Device: %s, Temperature %d Celsius reached critical limit of %u Celsius (Min/Max %s%s/%u%s)",
3335 PrintOut(LOG_INFO,
"Device: %s, Temperature %u Celsius reached limit of %u Celsius (Min/Max %s%s/%u%s)\n",
3340 if (currtemp < limit)
3341 reset_warning_mail(cfg, state, 12,
"Temperature %u Celsius dropped below %u Celsius", currtemp, limit);
3361 PrintOut(LOG_CRIT,
"Device: %s, Failed SMART usage Attribute: %d %s.\n", cfg.
name.c_str(), attr.
id, attrname.c_str());
3362 MailWarning(cfg, state, 2,
"Device: %s, Failed SMART usage Attribute: %d %s.", cfg.
name.c_str(), attr.
id, attrname.c_str());
3368 if (!( ( prefail && cfg.
prefail)
3369 || (!prefail && cfg.
usage )))
3377 if (attr.
id != prev.
id) {
3378 PrintOut(LOG_INFO,
"Device: %s, same Attribute has different ID numbers: %d = %d\n",
3379 cfg.
name.c_str(), attr.
id, prev.
id);
3384 bool valchanged =
false;
3391 bool rawchanged =
false;
3399 if (!(valchanged || rawchanged))
3403 std::string currstr, prevstr;
3425 std::string msg =
strprintf(
"Device: %s, SMART %s Attribute: %d %s changed from %s to %s",
3426 cfg.
name.c_str(), (prefail ?
"Prefailure" :
"Usage"), attr.
id,
3428 prevstr.c_str(), currstr.c_str());
3433 PrintOut(LOG_CRIT,
"%s\n", msg.c_str());
3437 PrintOut(LOG_INFO,
"%s\n", msg.c_str());
3444 bool firstpass,
bool allow_selftests)
3449 const char * name = cfg.
name.c_str();
3456 const char * mode = 0;
3457 if (0 <= powermode && powermode < 0xff) {
3462 if (powermode2 > powermode)
3463 PrintOut(LOG_INFO,
"Device: %s, CHECK POWER STATUS spins up disk (0x%02x -> 0x%02x)\n", name, powermode, powermode2);
3464 powermode = powermode2;
3516 mode=
"ACTIVE or IDLE";
3520 PrintOut(LOG_CRIT,
"Device: %s, CHECK POWER STATUS returned %d, not ATA compliant, ignoring -n Directive\n",
3533 PrintOut(LOG_INFO,
"Device: %s, is in %s mode, suspending checks\n", name, mode);
3540 PrintOut(LOG_INFO,
"Device: %s, %s mode ignored due to reached limit of skipped checks (%d check%s skipped)\n",
3547 PrintOut(LOG_INFO,
"Device: %s, is back in %s mode, resuming checks (%d check%s skipped)\n",
3558 PrintOut(LOG_INFO,
"Device: %s, not capable of SMART self-check\n",name);
3559 MailWarning(cfg, state, 5,
"Device: %s, not capable of SMART self-check", name);
3562 else if (status==1){
3563 PrintOut(LOG_CRIT,
"Device: %s, FAILED SMART self-check. BACK UP DATA NOW!\n", name);
3564 MailWarning(cfg, state, 1,
"Device: %s, FAILED SMART self-check. BACK UP DATA NOW!", name);
3578 PrintOut(LOG_CRIT,
"Device: %s, failed to read SMART Attribute Data\n", name);
3579 MailWarning(cfg, state, 6,
"Device: %s, failed to read SMART Attribute Data", name);
3589 :
"Total unreadable (pending) sectors" ));
3594 :
"Total offline uncorrectable sectors"));
3640 int errcnt1 = -1, errcnt2 = -1;
3647 int newc = (errcnt1 >= errcnt2 ? errcnt1 : errcnt2);
3652 MailWarning(cfg, state, 7,
"Device: %s, Read SMART Error Log Failed", name);
3657 PrintOut(LOG_CRIT,
"Device: %s, ATA error count increased from %d to %d\n",
3659 MailWarning(cfg, state, 4,
"Device: %s, ATA error count increased from %d to %d",
3692 const char * name = cfg.
name.c_str();
3694 uint8_t asc = 0, ascq = 0;
3695 uint8_t currenttemp = 0, triptemp = 0;
3698 &asc, &ascq, ¤ttemp, &triptemp)) {
3699 PrintOut(LOG_INFO,
"Device: %s, failed to read SMART values\n",
3701 MailWarning(cfg, state, 6,
"Device: %s, failed to read SMART values", name);
3708 PrintOut(LOG_CRIT,
"Device: %s, SMART Failure: %s\n", name, cp);
3709 MailWarning(cfg, state, 1,
"Device: %s, SMART Failure: %s", name, cp);
3710 }
else if (asc == 4 && ascq == 9) {
3711 PrintOut(LOG_INFO,
"Device: %s, self-test in progress\n", name);
3713 PrintOut(LOG_INFO,
"Device: %s, non-SMART asc,ascq: %d,%d\n",
3714 name, (
int)asc, (
int)ascq);
3716 PrintOut(LOG_INFO,
"Device: %s, SMART health: passed\n", name);
3768 const char * name = cfg.
name.c_str();
3774 PrintOut(LOG_INFO,
"Device: %s, failed to read NVMe SMART/Health Information\n", name);
3775 MailWarning(cfg, state, 6,
"Device: %s, failed to read NVMe SMART/Health Information", name);
3784 static const char *
const wnames[] =
3785 {
"LowSpare",
"Temperature",
"Reliability",
"R/O",
"VolMemBackup"};
3787 for (
unsigned b = 0, cnt = 0;
b < 8 ;
b++) {
3788 if (!(
w & (1 <<
b)))
3793 msg +=
"...";
break;
3795 if (
b >=
sizeof(wnames)/
sizeof(wnames[0])) {
3796 msg +=
"*Unknown*";
break;
3801 PrintOut(LOG_CRIT,
"Device: %s, Critical Warning (0x%02x): %s\n", name,
w, msg.c_str());
3802 MailWarning(cfg, state, 1,
"Device: %s, Critical Warning (0x%02x): %s", name,
w, msg.c_str());
3822 if (newcnt > oldcnt) {
3823 PrintOut(LOG_CRIT,
"Device: %s, number of Error Log entries increased from %" PRIu64
" to %" PRIu64
"\n",
3824 name, oldcnt, newcnt);
3825 MailWarning(cfg, state, 4,
"Device: %s, number of Error Log entries increased from %" PRIu64
" to %" PRIu64,
3826 name, oldcnt, newcnt);
3843 bool sts1 =
false, sts2 =
false;
3844 for (
const auto & cfg : configs) {
3845 if (cfg.offlinests_ns)
3847 if (cfg.selfteststs_ns)
3854 if (!
smi()->disable_system_auto_standby(
false)) {
3856 PrintOut(LOG_CRIT,
"System auto standby enable failed: %s\n",
smi()->get_errmsg());
3858 PrintOut(LOG_INFO,
"Disable auto standby not supported, ignoring ',ns' from %s%s%s\n",
3859 (sts1 ?
"-l offlinests,ns" :
""), (sts1 && sts2 ?
" and " :
""), (sts2 ?
"-l selfteststs,ns" :
""));
3860 sts1 = sts2 =
false;
3874 bool running =
false;
3875 for (
unsigned i = 0; i < configs.size() && !running; i++) {
3891 if (!
smi()->disable_system_auto_standby(
false))
3892 PrintOut(LOG_CRIT,
"Self-test(s) completed, system auto standby enable failed: %s\n",
3893 smi()->get_errmsg());
3895 PrintOut(LOG_INFO,
"Self-test(s) completed, system auto standby enabled\n");
3899 else if (!
smi()->disable_system_auto_standby(
true)) {
3901 PrintOut(LOG_INFO,
"Self-test(s) in progress, system auto standby disable rejected: %s\n",
3902 smi()->get_errmsg());
3908 PrintOut(LOG_INFO,
"Self-test(s) in progress, system auto standby disabled\n");
3918 for (
unsigned i = 0; i < configs.size(); i++) {
3923 PrintOut(LOG_INFO,
"Device: %s, skipped (interval=%d)\n", cfg.
name.c_str(),
3961static void ToggleDebugMode()
3964 PrintOut(LOG_INFO,
"Signal USR2 - enabling debug mode\n");
3965 if (!daemon_enable_console(
"smartd [Debug]")) {
3968 PrintOut(LOG_INFO,
"smartd debug mode enabled, PID=%d\n", getpid());
3971 PrintOut(LOG_INFO,
"enable console failed\n");
3974 daemon_disable_console();
3977 PrintOut(LOG_INFO,
"Signal USR2 - debug mode disabled\n");
3986 if (timenow < wakeuptime)
3988 return timenow + ct - (timenow - wakeuptime) % ct;
3995 time_t timenow = time(
nullptr);
3996 unsigned n = configs.size();
4006 for (
unsigned i = 0; i < n; i++) {
4012 if (!wakeuptime || state.
wakeuptime < wakeuptime)
4021 bool no_skip =
false;
4025 if (wakeuptime > timenow + ct) {
4026 PrintOut(LOG_INFO,
"System clock time adjusted to the past. Resetting next wakeup time.\n");
4027 wakeuptime = timenow + ct;
4028 for (
auto & state : states)
4029 state.wakeuptime = 0;
4034 sleep(wakeuptime+addtime-timenow);
4038 if (caughtsigUSR2) {
4044 timenow = time(
nullptr);
4047 if (!addtime && timenow > wakeuptime+60) {
4049 PrintOut(LOG_INFO,
"Sleep time was %d seconds too long, assuming wakeup from standby mode.\n",
4050 (
int)(timenow-wakeuptime));
4052 addtime = timenow-wakeuptime+20;
4054 int nextcheck = ct - addtime % ct;
4055 if (nextcheck <= 20)
4056 addtime += nextcheck;
4062 PrintOut(LOG_INFO,
"Signal USR1 - checking devices now rather than in %d seconds.\n",
4063 wakeuptime-timenow>0?(
int)(wakeuptime-timenow):0);
4065 sigwakeup = no_skip =
true;
4070 for (
auto & state : states)
4071 state.skip = (!no_skip && timenow < state.wakeuptime);
4083 PrintOut(priority,
"never[,N][,q], sleep[,N][,q], standby[,N][,q], idle[,N][,q]");
4086 PrintOut(priority,
"valid_regular_expression");
4089 PrintOut(priority,
"%s",
smi()->get_valid_dev_types_str().c_str());
4092 PrintOut(priority,
"normal, permissive");
4099 PrintOut(priority,
"error, selftest");
4102 PrintOut(priority,
"\"once\", \"daily\", \"diminishing\", \"test\", \"exec\"");
4108 PrintOut(priority,
"use, ignore, show, showall");
4114 PrintOut(priority,
"aam,[N|off], apm,[N|off], lookahead,[on|off], dsn,[on|off] "
4115 "security-freeze, standby,[N|off], wcache,[on|off]");
4118 PrintOut(priority,
"i=N, interval=N");
4124static int GetInteger(
const char *arg,
const char *name,
const char *token,
int lineno,
const char *cfgfile,
4125 int min,
int max,
char * suffix = 0)
4129 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s takes integer argument from %d to %d.\n",
4130 cfgfile, lineno, name, token, min, max);
4136 int val = strtol(arg,&endptr,10);
4140 if (!strcmp(endptr, suffix))
4141 endptr += strlen(suffix);
4146 if (!(!*endptr && min <= val && val <= max)) {
4147 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s has argument: %s; needs integer from %d to %d.\n",
4148 cfgfile, lineno, name, token, arg, min, max);
4158static int Get3Integers(
const char *arg,
const char *name,
const char *token,
int lineno,
const char *cfgfile,
4159 unsigned char *val1,
unsigned char *val2,
unsigned char *val3)
4161 unsigned v1 = 0, v2 = 0, v3 = 0;
4162 int n1 = -1, n2 = -1, n3 = -1, len;
4164 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s takes 1-3 integer argument(s) from 0 to 255.\n",
4165 cfgfile, lineno, name, token);
4170 if (!( sscanf(arg,
"%u%n,%u%n,%u%n", &v1, &n1, &v2, &n2, &v3, &n3) >= 1
4171 && (n1 == len || n2 == len || n3 == len) && v1 <= 255 && v2 <= 255 && v3 <= 255)) {
4172 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive: %s has argument: %s; needs 1-3 integer(s) from 0 to 255.\n",
4173 cfgfile, lineno, name, token, arg);
4176 *val1 = (
unsigned char)v1; *val2 = (
unsigned char)v2; *val3 = (
unsigned char)v3;
4184static const char * strtok_dequote(
const char * delimiters)
4186 const char * t = strtok(
nullptr, delimiters);
4187 if (!t || t[0] !=
'"')
4190 static std::string token;
4193 t = strtok(
nullptr, delimiters);
4197 int len = strlen(t);
4198 if (t[len-1] ==
'"') {
4199 token += std::string(t, len-1);
4204 return token.c_str();
4216 const char * name = cfg.
name.c_str();
4218 const char *delim =
" \n\t";
4221 const char *arg = 0;
4228 if (*token!=
'-' || strlen(token)!=2) {
4229 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): unknown Directive: %s\n",
4231 PrintOut(LOG_CRIT,
"Run smartd -D to print a list of valid Directives.\n");
4240 char plus[] =
"+", excl[] =
"!";
4245 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 0, 255, plus)) < 0)
4253 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 0, 255, plus)) < 0)
4261 if (!(arg = strtok(
nullptr, delim))) {
4263 }
else if (!strcmp(arg,
"normal")) {
4268 }
else if (!strcmp(arg,
"permissive")) {
4277 if (!(arg = strtok(
nullptr, delim))) {
4279 }
else if (!strcmp(arg,
"ignore")) {
4281 }
else if (!strcmp(arg,
"removable")) {
4283 }
else if (!strcmp(arg,
"auto")) {
4288 scan_types.push_back(arg);
4293 if (!(arg = strtok(
nullptr, delim)))
4321 if (!(arg = strtok(
nullptr, delim))) {
4323 }
else if (!strcmp(arg,
"selftest")) {
4326 }
else if (!strcmp(arg,
"error")) {
4329 }
else if (!strcmp(arg,
"xerror")) {
4332 }
else if (!strcmp(arg,
"offlinests")) {
4335 }
else if (!strcmp(arg,
"offlinests,ns")) {
4338 }
else if (!strcmp(arg,
"selfteststs")) {
4341 }
else if (!strcmp(arg,
"selfteststs,ns")) {
4344 }
else if (!strncmp(arg,
"scterc,",
sizeof(
"scterc,")-1)) {
4346 unsigned rt = ~0, wt = ~0;
int nc = -1;
4347 sscanf(arg,
"scterc,%u,%u%n", &rt, &wt, &nc);
4348 if (nc == (
int)strlen(arg) && rt <= 999 && wt <= 999) {
4371 if (!(arg = strtok(
nullptr, delim))) {
4373 }
else if (!strcmp(arg,
"on")) {
4375 }
else if (!strcmp(arg,
"off")) {
4383 if (!(arg = strtok(
nullptr, delim)))
4386 char *endptr =
nullptr;
4387 char *next = strchr(
const_cast<char*
>(arg),
',');
4394 if (!strcmp(arg,
"never"))
4396 else if (!strcmp(arg,
"sleep"))
4398 else if (!strcmp(arg,
"standby"))
4400 else if (!strcmp(arg,
"idle"))
4406 if (!badarg && next) {
4412 next = endptr + (*endptr !=
'\0');
4416 if (*next !=
'\0') {
4417 if (!strcmp(
"q", next))
4428 if (!(arg = strtok(
nullptr, delim))) {
4430 }
else if (!strcmp(arg,
"on")) {
4432 }
else if (!strcmp(arg,
"off")) {
4441 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous Test Directive -s %s\n",
4446 if (!(arg = strtok(
nullptr, delim))) {
4453 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): -s argument \"%s\" is INVALID extended regular expression. %s.\n",
4462 "[^]$()*+./:?^[|0-9LSCOncr-]+|"
4463 ":[0-9]{0,2}($|[^0-9])|:[0-9]{4,}|"
4464 ":[0-9]{3}-(000|[0-9]{0,2}($|[^0-9])|[0-9]{4,})"
4467 if (syntax_check.
execute(arg, 1, &range) && 0 <= range.rm_so && range.rm_so < range.rm_eo)
4468 PrintOut(LOG_INFO,
"File %s line %d (drive %s): warning, \"%.*s\" looks odd in "
4469 "extended regular expression \"%s\"\n",
4470 configfile, lineno, name, (
int)(range.rm_eo - range.rm_so), arg + range.rm_so, arg);
4475 if (!(arg = strtok(
nullptr, delim)))
4479 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous Address Directive -m %s\n",
4486 if (!(arg = strtok(
nullptr, delim)))
4488 else if (!strcmp(arg,
"once"))
4490 else if (!strcmp(arg,
"daily"))
4492 else if (!strcmp(arg,
"diminishing"))
4494 else if (!strcmp(arg,
"test"))
4496 else if (!strcmp(arg,
"exec")) {
4500 arg = strtok_dequote(delim);
4501 if (arg && arg[0] ==
'"') {
4502 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive %s 'exec' argument: missing closing quote\n",
4507 arg = strtok(
nullptr, delim);
4510 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Directive %s 'exec' argument must be followed by executable path.\n",
4516 PrintOut(LOG_INFO,
"File %s line %d (drive %s): ignoring previous mail Directive -M exec %s\n",
4525 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255)) < 0)
4531 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255)) < 0)
4537 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255, excl)) < 0)
4545 if ((val =
GetInteger((arg = strtok(
nullptr, delim)), name, token, lineno,
configfile, 1, 255, excl)) < 0)
4559 if (!(arg = strtok(
nullptr, delim))) {
4567 if (!(arg = strtok(
nullptr, delim))) {
4569 }
else if (!strcmp(arg,
"use")) {
4571 }
else if (!strcmp(arg,
"ignore")) {
4573 }
else if (!strcmp(arg,
"show")) {
4575 }
else if (!strcmp(arg,
"showall")) {
4584 if (!(arg = strtok(
nullptr, delim))) {
4588 char arg2[16+1];
unsigned uval;
4589 int n1 = -1, n2 = -1, n3 = -1, len = strlen(arg);
4590 if (sscanf(arg,
"%16[^,=]%n%*[,=]%n%u%n", arg2, &n1, &n2, &uval, &n3) >= 1
4591 && (n1 == len || n2 > 0)) {
4592 bool on = (n2 > 0 && !strcmp(arg+n2,
"on"));
4593 bool off = (n2 > 0 && !strcmp(arg+n2,
"off"));
4597 if (!strcmp(arg2,
"aam")) {
4600 else if (uval <= 254)
4605 else if (!strcmp(arg2,
"apm")) {
4608 else if (1 <= uval && uval <= 254)
4613 else if (!strcmp(arg2,
"lookahead")) {
4621 else if (!strcmp(arg,
"security-freeze")) {
4624 else if (!strcmp(arg2,
"standby")) {
4627 else if (uval <= 255)
4632 else if (!strcmp(arg2,
"wcache")) {
4640 else if (!strcmp(arg2,
"dsn")) {
4659 if (!(arg = strtok(
nullptr, delim))) {
4663 int n = 0, nc = -1, len = strlen(arg);
4664 if ( ( sscanf(arg,
"i=%d%n", &n, &nc) == 1
4665 || sscanf(arg,
"interval=%d%n", &n, &nc) == 1)
4666 && nc == len && n >= 10)
4675 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): unknown Directive: %s\n",
4677 PrintOut(LOG_CRIT,
"Run smartd -D to print a list of valid Directives.\n");
4681 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Missing argument to %s Directive\n",
4685 PrintOut(LOG_CRIT,
"File %s line %d (drive %s): Invalid argument to %s Directive: %s\n",
4688 if (missingarg || badarg) {
4689 PrintOut(LOG_CRIT,
"Valid arguments to %s Directive are: ", token);
4699#define SCANDIRECTIVE "DEVICESCAN"
4713 const char *delim =
" \n\t";
4716 const char * name = strtok(line, delim);
4717 if (!name || *name ==
'#')
4722 if (!strcmp(
"DEFAULT", name)) {
4730 conf_entries.push_back(default_conf);
4732 dev_config & cfg = (retval ? conf_entries.back() : default_conf);
4739 while (
char * token = strtok(
nullptr, delim)) {
4753 if (retval != -1 && scan_types.size() > 1) {
4754 PrintOut(LOG_CRIT,
"Drive: %s, invalid multiple -d TYPE Directives on line %d of file %s\n",
4770 PrintOut(LOG_INFO,
"Drive: %s, implied '-a' Directive on line %d of file %s\n",
4784 PrintOut(LOG_CRIT,
"Drive: %s, -M Directive(s) on line %d of file %s need -m ADDRESS Directive\n",
4793 PrintOut(LOG_CRIT,
"Drive: %s, -m <nomailer> Directive on line %d of file %s needs -M exec Directive\n",
4818 const int MAXLINELEN = 256;
4820 const int MAXCONTLINE = 1023;
4827 int ret = (errno!=ENOENT ? -3 : -2);
4828 PrintOut(LOG_CRIT,
"%s: Unable to open configuration file %s\n",
4844 if (
ParseConfigLine(conf_entries, default_conf, scan_types, 0, fakeconfig) != -1)
4845 throw std::logic_error(
"Internal error parsing " SCANDIRECTIVE);
4850 setmode(fileno(f), O_TEXT);
4857 int lineno = 1, cont = 0, contlineno = 0;
4858 char line[MAXLINELEN+2];
4859 char fullline[MAXCONTLINE+1];
4862 int len=0,scandevice;
4868 memset(line,0,
sizeof(line));
4871 code=fgets(line, MAXLINELEN+2, f);
4876 scandevice =
ParseConfigLine(conf_entries, default_conf, scan_types, contlineno, fullline);
4894 if (len>MAXLINELEN){
4896 if (line[len-1]==
'\n')
4897 warn=
"(including newline!) ";
4900 PrintOut(LOG_CRIT,
"Error: line %d of file %s %sis more than MAXLINELEN=%d characters.\n",
4901 (
int)contlineno,
configfile,warn,(
int)MAXLINELEN);
4906 if ((comment=strchr(line,
'#'))){
4912 if (cont+len>MAXCONTLINE){
4913 PrintOut(LOG_CRIT,
"Error: continued line %d (actual line %d) of file %s is more than MAXCONTLINE=%d characters.\n",
4914 lineno, (
int)contlineno,
configfile, (
int)MAXCONTLINE);
4919 snprintf(fullline+cont,
sizeof(fullline)-cont,
"%s" ,line);
4923 if ( (lastslash=strrchr(line,
'\\')) && !strtok(lastslash+1,
" \n\t")){
4924 *(fullline+(cont-len)+(lastslash-line))=
' ';
4930 scandevice =
ParseConfigLine(conf_entries, default_conf, scan_types, contlineno, fullline);
4954 PrintOut(LOG_CRIT,
"=======> VALID ARGUMENTS ARE: ");
4956 PrintOut(LOG_CRIT,
"Error constructing argument list for option %c", opt);
4966 if (path.empty() || path[0] ==
'/')
4971 PrintOut(LOG_CRIT,
"=======> INVALID ARGUMENT TO -%c: %s <=======\n\n", option, path.c_str());
4972 PrintOut(LOG_CRIT,
"Error: relative path names are not allowed\n\n");
4983 configfile = SMARTMONTOOLS_SYSCONFDIR
"/smartd.conf";
4984 warning_script = SMARTMONTOOLS_SMARTDSCRIPTDIR
"/smartd_warning.sh";
4987 static std::string configfile_str = exedir +
"/smartd.conf";
4993 static const char shortopts[] =
"c:l:q:dDni:p:r:s:A:B:w:Vh?"
4994#if defined(HAVE_POSIX_API) || defined(_WIN32)
4997#ifdef HAVE_LIBCAP_NG
5002 struct option longopts[] = {
5003 {
"configfile", required_argument, 0,
'c' },
5004 {
"logfacility", required_argument, 0,
'l' },
5005 {
"quit", required_argument, 0,
'q' },
5006 {
"debug", no_argument, 0,
'd' },
5007 {
"showdirectives", no_argument, 0,
'D' },
5008 {
"interval", required_argument, 0,
'i' },
5010 {
"no-fork", no_argument, 0,
'n' },
5012 {
"service", no_argument, 0,
'n' },
5014 {
"pidfile", required_argument, 0,
'p' },
5015 {
"report", required_argument, 0,
'r' },
5016 {
"savestates", required_argument, 0,
's' },
5017 {
"attributelog", required_argument, 0,
'A' },
5018 {
"drivedb", required_argument, 0,
'B' },
5019 {
"warnexec", required_argument, 0,
'w' },
5020 {
"version", no_argument, 0,
'V' },
5021 {
"license", no_argument, 0,
'V' },
5022 {
"copyright", no_argument, 0,
'V' },
5023 {
"help", no_argument, 0,
'h' },
5024 {
"usage", no_argument, 0,
'h' },
5025#if defined(HAVE_POSIX_API) || defined(_WIN32)