14#define __STDC_FORMAT_MACROS 1
30#if defined(__FreeBSD__)
43#include "svnversion.h"
67 pout(
"\nUse smartctl -h to get a usage summary\n\n");
80 jglb[
"json_format_version"][0] = 1;
81 jglb[
"json_format_version"][1] = 0;
85 int ver[3] = { 0, 0, 0 };
86 sscanf(PACKAGE_VERSION,
"%d.%d.%d", ver, ver+1, ver+2);
87 jref[
"version"][0] = ver[0];
88 jref[
"version"][1] = ver[1];
90 jref[
"version"][2] = ver[2];
92#ifdef SMARTMONTOOLS_RELEASE_DATE
93 jref[
"pre_release"] =
false;
95 jref[
"pre_release"] =
true;
97#ifdef SMARTMONTOOLS_SVN_REV
98 jref[
"svn_revision"] = SMARTMONTOOLS_SVN_REV;
105 jref[
"argv"][0] =
"smartctl";
106 for (
int i = 1; i < argc; i++)
107 jref[
"argv"][i] = argv[i];
115 pout(
"Usage: smartctl [options] device\n\n");
117"============================================ SHOW INFORMATION OPTIONS =====\n\n"
118" -h, --help, --usage\n"
119" Display this help and exit\n\n"
120" -V, --version, --copyright, --license\n"
121" Print license, copyright, and version information and exit\n\n"
123" Show identity information for device\n\n"
124" --identify[=[w][nvb]]\n"
125" Show words and bits from IDENTIFY DEVICE data (ATA)\n\n"
126" -g NAME, --get=NAME\n"
127" Get device setting: all, aam, apm, dsn, lookahead, security,\n"
128" wcache, rcache, wcreorder, wcache-sct\n\n"
130" Show all SMART information for device\n\n"
132" Show all information for device\n\n"
134" Scan for devices\n\n"
136" Scan for devices and try to open each device\n\n"
139"================================== SMARTCTL RUN-TIME BEHAVIOR OPTIONS =====\n\n"
140" -j, --json[=cgiosuvy]\n"
141" Print output in JSON or YAML format\n\n"
142" -q TYPE, --quietmode=TYPE (ATA)\n"
143" Set smartctl quiet mode to one of: errorsonly, silent, noserial\n\n"
144" -d TYPE, --device=TYPE\n"
145" Specify device type to one of:\n"
147" -T TYPE, --tolerance=TYPE (ATA)\n"
148" Tolerance: normal, conservative, permissive, verypermissive\n\n"
149" -b TYPE, --badsum=TYPE (ATA)\n"
150" Set action on bad checksum to one of: warn, exit, ignore\n\n"
151" -r TYPE, --report=TYPE\n"
152" Report transactions (see man page)\n\n"
153" -n MODE[,STATUS[,STATUS2]], --nocheck=MODE[,STATUS[,STATUS2]] (ATA, SCSI)\n"
154" No check if: never, sleep, standby, idle (see man page)\n\n",
157"============================== DEVICE FEATURE ENABLE/DISABLE COMMANDS =====\n\n"
158" -s VALUE, --smart=VALUE\n"
159" Enable/disable SMART on device (on/off)\n\n"
160" -o VALUE, --offlineauto=VALUE (ATA)\n"
161" Enable/disable automatic offline testing on device (on/off)\n\n"
162" -S VALUE, --saveauto=VALUE (ATA)\n"
163" Enable/disable Attribute autosave on device (on/off)\n\n"
164" -s NAME[,VALUE], --set=NAME[,VALUE]\n"
165" Enable/disable/change device setting: aam,[N|off], apm,[N|off],\n"
166" dsn,[on|off], lookahead,[on|off], security-freeze,\n"
167" standby,[N|off|now], wcache,[on|off], rcache,[on|off],\n"
168" wcreorder,[on|off[,p]], wcache-sct,[ata|on|off[,p]]\n\n"
171"======================================= READ AND DISPLAY DATA OPTIONS =====\n\n"
173" Show device SMART health status\n\n"
174" -c, --capabilities (ATA, NVMe)\n"
175" Show device SMART capabilities\n\n"
177" Show device SMART vendor-specific Attributes and values\n\n"
178" -f FORMAT, --format=FORMAT (ATA)\n"
179" Set output format for attributes: old, brief, hex[,id|val]\n\n"
180" -l TYPE, --log=TYPE\n"
181" Show device log. TYPE: error, selftest, selective, directory[,g|s],\n"
182" xerror[,N][,error], xselftest[,N][,selftest], background,\n"
183" sasphy[,reset], sataphy[,reset], scttemp[sts,hist],\n"
184" scttempint,N[,p], scterc[,N,M][,p|reset], devstat[,N], defects[,N],\n"
185" ssd, gplog,N[,RANGE], smartlog,N[,RANGE], nvmelog,N,SIZE\n"
186" tapedevstat, zdevstat, envrep, farm\n\n"
187" -v N,OPTION , --vendorattribute=N,OPTION (ATA)\n"
188" Set display OPTION for vendor Attribute N (see man page)\n\n"
189" -F TYPE, --firmwarebug=TYPE (ATA)\n"
190" Use firmware bug workaround:\n"
192" -P TYPE, --presets=TYPE (ATA)\n"
193" Drive-specific presets: use, ignore, show, showall\n\n"
194" -B [+]FILE, --drivedb=[+]FILE (ATA)\n"
195" Read and replace [add] drive database from FILE\n"
200#ifdef SMARTMONTOOLS_DRIVEDBDIR
204 get_drivedb_path_default()
209"============================================ DEVICE SELF-TEST OPTIONS =====\n\n"
210" -t TEST, --test=TEST\n"
211" Run test. TEST: offline, short, long, conveyance, force, vendor,N,\n"
212" select,M-N, pending,N, afterselect,[on|off]\n\n"
214" Do test in captive mode (along with -t)\n\n"
216" Abort any non-captive test on device\n\n"
219 if (!examples.empty())
220 pout(
"%s\n", examples.c_str());
232 return "errorsonly, silent, noserial";
236 return "normal, conservative, permissive, verypermissive";
238 return "warn, exit, ignore";
240 return "[+]<FILE_NAME>";
242 return "ioctl[,N], ataioctl[,N], scsiioctl[,N], nvmeioctl[,N]";
248 return "error, selftest, selective, directory[,g|s], "
249 "xerror[,N][,error], xselftest[,N][,selftest], "
250 "background, sasphy[,reset], sataphy[,reset], "
251 "scttemp[sts,hist], scttempint,N[,p], "
252 "scterc[,N,M][,p|reset], devstat[,N], defects[,N], "
253 "ssd, gplog,N[,RANGE], smartlog,N[,RANGE], "
254 "nvmelog,N,SIZE, tapedevstat, zdevstat, envrep, farm";
256 return "use, ignore, show, showall";
258 return "offline, short, long, conveyance, force, vendor,N, select,M-N, "
259 "pending,N, afterselect,[on|off]";
263 return "never, sleep[,STATUS[,STATUS2]], standby[,STATUS[,STATUS2]], "
264 "idle[,STATUS[,STATUS2]]";
266 return "old, brief, hex[,id|val]";
268 return "aam, apm, dsn, lookahead, security, wcache, rcache, wcreorder, wcache-sct";
270 return "aam,[N|off], apm,[N|off], dsn,[on|off], lookahead,[on|off], security-freeze, "
271 "standby,[N|off|now], wcache,[on|off], rcache,[on|off], wcreorder,[on|off[,p]], "
272 "wcache-sct,[ata|on|off[,p]]";
276 return "c, g, i, o, s, u, v, y";
278 return "n, wn, w, v, wv, wb";
290 jerr(
"=======> VALID ARGUMENTS ARE:\n\thelp\n%s\n<=======\n",
297 char separator = strchr(
s.c_str(),
'\n') ?
'\n' :
' ';
298 jerr(
"=======> VALID ARGUMENTS ARE:%c%s%c<=======\n", separator,
s.c_str(), separator);
320 const char *shortopts =
"h?Vq:d:T:b:r:s:o:S:HcAl:iaxv:P:t:CXF:n:B:f:g:j";
322 struct option longopts[] = {
323 {
"help", no_argument, 0,
'h' },
324 {
"usage", no_argument, 0,
'h' },
325 {
"version", no_argument, 0,
'V' },
326 {
"copyright", no_argument, 0,
'V' },
327 {
"license", no_argument, 0,
'V' },
328 {
"quietmode", required_argument, 0,
'q' },
329 {
"device", required_argument, 0,
'd' },
330 {
"tolerance", required_argument, 0,
'T' },
331 {
"badsum", required_argument, 0,
'b' },
332 {
"report", required_argument, 0,
'r' },
333 {
"smart", required_argument, 0,
opt_smart },
334 {
"offlineauto", required_argument, 0,
'o' },
335 {
"saveauto", required_argument, 0,
'S' },
336 {
"health", no_argument, 0,
'H' },
337 {
"capabilities", no_argument, 0,
'c' },
338 {
"attributes", no_argument, 0,
'A' },
339 {
"log", required_argument, 0,
'l' },
340 {
"info", no_argument, 0,
'i' },
341 {
"all", no_argument, 0,
'a' },
342 {
"xall", no_argument, 0,
'x' },
343 {
"vendorattribute", required_argument, 0,
'v' },
344 {
"presets", required_argument, 0,
'P' },
345 {
"test", required_argument, 0,
't' },
346 {
"captive", no_argument, 0,
'C' },
347 {
"abort", no_argument, 0,
'X' },
348 {
"firmwarebug", required_argument, 0,
'F' },
349 {
"nocheck", required_argument, 0,
'n' },
350 {
"drivedb", required_argument, 0,
'B' },
351 {
"format", required_argument, 0,
'f' },
352 {
"get", required_argument, 0,
'g' },
353 {
"json", optional_argument, 0,
'j' },
355 {
"set", required_argument, 0,
opt_set },
356 {
"scan", no_argument, 0,
opt_scan },
361 char extraerror[256];
362 memset(extraerror, 0,
sizeof(extraerror));
366 bool use_default_db =
true;
367 bool output_format_set =
false;
369 bool badarg =
false, captive =
false;
375 while ((optchar = getopt_long(argc, argv, shortopts, longopts, 0)) != -1) {
379 bool optarg_is_set = !!optarg;
380 #ifdef __clang_analyzer__
381 if (!optarg_is_set) optarg = (
char *)
"";
390 if (!strcmp(optarg,
"errorsonly")) {
393 }
else if (!strcmp(optarg,
"silent")) {
396 }
else if (!strcmp(optarg,
"noserial")) {
403 if (!strcmp(optarg,
"test"))
404 print_type_only =
true;
405 else if (!strcmp(optarg,
"auto")) {
411 scan_types.push_back(optarg);
415 if (!strcmp(optarg,
"normal")) {
418 }
else if (!strcmp(optarg,
"conservative")) {
420 }
else if (!strcmp(optarg,
"permissive")) {
423 }
else if (!strcmp(optarg,
"verypermissive")) {
430 if (!strcmp(optarg,
"warn")) {
432 }
else if (!strcmp(optarg,
"exit")) {
434 }
else if (!strcmp(optarg,
"ignore")) {
442 int n1 = -1, n2 = -1, len = strlen(optarg);
443 char s[9+1];
unsigned i = 1;
444 sscanf(optarg,
"%9[a-z]%n,%u%n",
s, &n1, &i, &n2);
445 if (!((n1 == len || n2 == len) && 1 <= i && i <= 4)) {
447 }
else if (!strcmp(
s,
"ioctl")) {
449 }
else if (!strcmp(
s,
"ataioctl")) {
451 }
else if (!strcmp(
s,
"scsiioctl")) {
453 }
else if (!strcmp(
s,
"nvmeioctl")) {
463 if (!strcmp(optarg,
"on")) {
466 }
else if (!strcmp(optarg,
"off")) {
469 }
else if (optchar ==
's') {
470 goto case_s_continued;
477 if (!strcmp(optarg,
"on")) {
480 }
else if (!strcmp(optarg,
"off")) {
488 if (!strcmp(optarg,
"on")) {
491 }
else if (!strcmp(optarg,
"off")) {
504 if (!strcmp(optarg,
"swapid"))
517 int n1 = -1, n2 = -1, len = strlen(optarg);
519 sscanf(optarg,
"error%n,%u%n", &n1, &val, &n2);
523 else if (n2 == len && val > 0)
527 }
else if (!strcmp(optarg,
"selftest")) {
529 }
else if (!strcmp(optarg,
"selective")) {
531 }
else if (!strcmp(optarg,
"directory")) {
533 }
else if (!strcmp(optarg,
"directory,s")) {
535 }
else if (!strcmp(optarg,
"directory,g")) {
537 }
else if (!strcmp(optarg,
"genstats")) {
539 }
else if (!strcmp(optarg,
"sasphy")) {
541 }
else if (!strcmp(optarg,
"sasphy,reset")) {
543 }
else if (!strcmp(optarg,
"sataphy")) {
545 }
else if (!strcmp(optarg,
"sataphy,reset")) {
547 }
else if (!strcmp(optarg,
"background")) {
549 }
else if (!strcmp(optarg,
"ssd")) {
552 }
else if (!strcmp(optarg,
"scterc")) {
554 }
else if (!strcmp(optarg,
"scttemp")) {
556 }
else if (!strcmp(optarg,
"envrep")) {
558 }
else if (!strcmp(optarg,
"scttempsts")) {
560 }
else if (!strcmp(optarg,
"scttemphist")) {
562 }
else if (!strcmp(optarg,
"farm")) {
564 }
else if (!strcmp(optarg,
"tapealert")) {
566 }
else if (!strcmp(optarg,
"tapedevstat")) {
568 }
else if (!strcmp(optarg,
"zdevstat")) {
570 }
else if (!strncmp(optarg,
"scttempint,",
sizeof(
"scstempint,")-1)) {
571 unsigned interval = 0;
int n1 = -1, n2 = -1, len = strlen(optarg);
572 if (!( sscanf(optarg,
"scttempint,%u%n,p%n", &interval, &n1, &n2) == 1
573 && 0 < interval && interval <= 0xffff && (n1 == len || n2 == len))) {
574 snprintf(extraerror,
sizeof(extraerror),
"Option -l scttempint,N[,p] must have positive integer N\n");
580 }
else if (!strncmp(optarg,
"devstat",
sizeof(
"devstat")-1)) {
581 int n1 = -1, n2 = -1, len = strlen(optarg);
583 sscanf(optarg,
"devstat%n,%u%n", &n1, &val, &n2);
588 sscanf(optarg,
"devstat,0x%x%n", &val, &n2);
589 if (n2 == len && val <= 0xff)
596 int n1 = -1, n2 = -1, len = strlen(optarg);
598 sscanf(optarg,
"defects%n,%u%n", &n1, &val, &n2);
602 else if (n2 == len && val <= 0xffff * 32 - 1)
607 }
else if (!strncmp(optarg,
"xerror",
sizeof(
"xerror")-1)) {
608 int n1 = -1, n2 = -1, len = strlen(optarg);
610 sscanf(optarg,
"xerror%n,error%n", &n1, &n2);
611 if (!(n1 == len || n2 == len)) {
613 sscanf(optarg,
"xerror,%u%n,error%n", &val, &n1, &n2);
615 if ((n1 == len || n2 == len) && val > 0) {
622 }
else if (!strncmp(optarg,
"xselftest",
sizeof(
"xselftest")-1)) {
623 int n1 = -1, n2 = -1, len = strlen(optarg);
625 sscanf(optarg,
"xselftest%n,selftest%n", &n1, &n2);
626 if (!(n1 == len || n2 == len)) {
628 sscanf(optarg,
"xselftest,%u%n,selftest%n", &val, &n1, &n2);
630 if ((n1 == len || n2 == len) && val > 0) {
637 }
else if (!strncmp(optarg,
"scterc,",
sizeof(
"scterc,")-1)) {
638 int n1 = -1, n2 = -1, len = strlen(optarg);
639 unsigned rt = ~0, wt = ~0;
640 sscanf(optarg,
"scterc,%u,%u%n,p%n", &rt, &wt, &n1, &n2);
641 if ((n1 == len || n2 == len) && rt <= 999 && wt <= 999) {
645 }
else if (!strcmp(optarg,
"scterc,p")) {
647 }
else if (!strcmp(optarg,
"scterc,reset")) {
651 snprintf(extraerror,
sizeof(extraerror),
"Option -l scterc[,READTIME,WRITETIME][,p|reset] syntax error\n");
654 }
else if ( !strncmp(optarg,
"gplog," ,
sizeof(
"gplog," )-1)
655 || !strncmp(optarg,
"smartlog,",
sizeof(
"smartlog,")-1)) {
656 unsigned logaddr = ~0U;
unsigned page = 0, nsectors = 1;
char sign = 0;
657 int n1 = -1, n2 = -1, n3 = -1, len = strlen(optarg);
658 sscanf(optarg,
"%*[a-z],0x%x%n,%u%n%c%u%n",
659 &logaddr, &n1, &page, &n2, &sign, &nsectors, &n3);
660 if (len > n2 && n3 == -1 && !strcmp(optarg+n2,
"-max")) {
661 nsectors = ~0U; sign =
'+'; n3 = len;
663 bool gpl = (optarg[0] ==
'g');
664 const char * erropt = (gpl ?
"gplog" :
"smartlog");
665 if (!( n1 == len || n2 == len
666 || (n3 == len && (sign ==
'+' || sign ==
'-')))) {
667 snprintf(extraerror,
sizeof(extraerror),
"Option -l %s,ADDR[,FIRST[-LAST|+SIZE]] syntax error\n", erropt);
670 else if (!( logaddr <= 0xff && page <= (gpl ? 0xffffU : 0x00ffU)
672 && (nsectors <= (gpl ? 0xffffU : 0xffU) || nsectors == ~0U)
673 && (sign !=
'-' || page <= nsectors) )) {
674 snprintf(extraerror,
sizeof(extraerror),
"Option -l %s,ADDR[,FIRST[-LAST|+SIZE]] parameter out of range\n", erropt);
680 req.
nsectors = (sign ==
'-' ? nsectors-page+1 : nsectors);
686 int n = -1, len = strlen(optarg);
687 unsigned page = 0,
size = 0;
688 sscanf(optarg,
"nvmelog,0x%x,0x%x%n", &page, &
size, &n);
689 if (n == len && page <= 0xff && 0 <
size &&
size <= 0x4000) {
707 for (
int i = 0; optarg[i]; i++) {
713 default: badarg =
true;
768 if (!output_format_set)
773 if (!strcmp(optarg,
"help")) {
776 pout(
"The valid arguments to -v are:\n\thelp\n%s\n",
784 if (!strcmp(optarg,
"use")) {
786 }
else if (!strcmp(optarg,
"ignore")) {
788 }
else if (!strcmp(optarg,
"show")) {
790 }
else if (!strcmp(optarg,
"showall")) {
795 return (cnt >= 0 ? cnt : 0);
805 if (!strcmp(optarg,
"offline")) {
809 }
else if (!strcmp(optarg,
"short")) {
814 }
else if (!strcmp(optarg,
"long")) {
819 }
else if (!strcmp(optarg,
"conveyance")) {
822 }
else if (!strcmp(optarg,
"force")) {
825 }
else if (!strcmp(optarg,
"afterselect,on")) {
828 }
else if (!strcmp(optarg,
"afterselect,off")) {
831 }
else if (!strncmp(optarg,
"pending,",strlen(
"pending,"))) {
836 i=(int)strtol(optarg+strlen(
"pending,"), &tailptr, 10);
837 if (errno || *tailptr !=
'\0') {
838 snprintf(extraerror,
sizeof(extraerror),
"Option -t pending,N requires N to be a non-negative integer\n");
840 }
else if (i<0 || i>65535) {
841 snprintf(extraerror,
sizeof(extraerror),
"Option -t pending,N (N=%d) must have 0 <= N <= 65535\n", i);
846 }
else if (!strncmp(optarg,
"select",strlen(
"select"))) {
850 uint64_t start, stop;
int mode;
852 snprintf(extraerror,
sizeof(extraerror),
"Option -t select,M-N must have non-negative integer M and N\n");
857 snprintf(extraerror,
sizeof(extraerror),
"ERROR: Start LBA (%" PRIu64
") > ending LBA (%" PRId64
") in argument \"%s\"\n",
858 start, stop, optarg);
860 snprintf(extraerror,
sizeof(extraerror),
"ERROR: No more than five selective self-test spans may be"
871 }
else if (!strncmp(optarg,
"scttempint",
sizeof(
"scstempint")-1)) {
872 snprintf(extraerror,
sizeof(extraerror),
"-t scttempint is no longer supported, use -l scttempint instead\n");
874 }
else if (!strncmp(optarg,
"vendor,",
sizeof(
"vendor,")-1)) {
875 unsigned subcmd = ~0U;
int n = -1;
876 if (!( sscanf(optarg,
"%*[a-z],0x%x%n", &subcmd, &n) == 1
877 && subcmd <= 0xff && n == (
int)strlen(optarg))) {
878 snprintf(extraerror,
sizeof(extraerror),
"Option -t vendor,0xNN syntax error\n");
898 if (!strcmp(optarg,
"never")) {
903 int n1 = -1, n2 = -1, n3 = -1, len = strlen(optarg);
905 sscanf(optarg,
"%7[a-z]%n,%u%n,%u%n",
s, &n1, &i, &n2, &j, &n3);
906 if (!((n1 == len || n2 == len || n3 == len) && i <= 255 && j <= 255))
908 else if (!strcmp(
s,
"sleep")) {
911 }
else if (!strcmp(
s,
"standby")) {
914 }
else if (!strcmp(
s,
"idle")) {
926 if (!strcmp(optarg,
"old")) {
928 output_format_set =
true;
930 else if (!strcmp(optarg,
"brief")) {
932 output_format_set =
true;
934 else if (!strcmp(optarg,
"hex"))
937 else if (!strcmp(optarg,
"hex,id"))
939 else if (!strcmp(optarg,
"hex,val"))
946 const char * path = optarg;
947 if (*path ==
'+' && path[1])
950 use_default_db =
false;
966 bool get = (optchar ==
'g');
967 char name[16+1];
unsigned val;
968 int n1 = -1, n2 = -1, n3 = -1, len = strlen(optarg);
969 if (sscanf(optarg,
"%16[^,=]%n%*[,=]%n%u%n", name, &n1, &n2, &val, &n3) >= 1
970 && (n1 == len || (!get && n2 > 0))) {
974 bool persistent =
false;
977 int len2 = strlen(optarg + n2);
978 char * tmp = strstr(optarg+n2,
",p");
980 if (tmp && (strlen(tmp) == 2)) {
982 len2 = strlen(optarg+n2) - 2;
985 if (strcmp(name,
"wcache-sct") != 0 &&
986 strcmp(name,
"wcreorder") != 0)
989 on = !strncmp(optarg+n2,
"on", len2);
990 off = !strncmp(optarg+n2,
"off", len2);
991 ata = !strncmp(optarg+n2,
"ata", len2);
996 if (get && !strcmp(name,
"all")) {
1003 else if (!strcmp(name,
"aam")) {
1008 else if (val <= 254)
1011 snprintf(extraerror,
sizeof(extraerror),
"Option -s aam,N must have 0 <= N <= 254\n");
1015 else if (!strcmp(name,
"apm")) {
1020 else if (1 <= val && val <= 254)
1023 snprintf(extraerror,
sizeof(extraerror),
"Option -s apm,N must have 1 <= N <= 254\n");
1027 else if (!strcmp(name,
"lookahead")) {
1038 else if (!strcmp(name,
"wcreorder")) {
1050 else if (!strcmp(name,
"wcache-sct")) {
1064 else if (!strcmp(name,
"rcache")) {
1074 else if (get && !strcmp(name,
"security")) {
1077 else if (!get && !strcmp(optarg,
"security-freeze")) {
1080 else if (!get && !strcmp(optarg,
"standby,now")) {
1084 else if (!get && !strcmp(name,
"standby")) {
1088 }
else if (val <= 255) {
1092 snprintf(extraerror,
sizeof(extraerror),
"Option -s standby,N must have 0 <= N <= 255\n");
1096 else if (!strcmp(name,
"wcache")) {
1112 else if (!strcmp(name,
"dsn")) {
1146 bool json_verbose =
false;
1147 if (optarg_is_set) {
1148 for (
int i = 0; optarg[i]; i++) {
1149 switch (optarg[i]) {
1156 case 'v': json_verbose =
true;
break;
1158 default: badarg =
true;
1172 arg = argv[optind <= argc ? optind - 1 : argc - 1];
1174 if (arg[1] ==
'-' && optchar !=
'h') {
1176 if (optopt && (optopt >
'~' || strchr(shortopts, optopt))) {
1177 jerr(
"=======> ARGUMENT REQUIRED FOR OPTION: %s\n", arg+2);
1180 jerr(
"=======> UNRECOGNIZED OPTION: %s\n",arg+2);
1182 pout(
"=======> %s", extraerror);
1186 if (0 < optopt && optopt <
'~') {
1190 if (strchr(shortopts, optopt) != NULL) {
1191 jerr(
"=======> ARGUMENT REQUIRED FOR OPTION: %c\n", optopt);
1194 jerr(
"=======> UNRECOGNIZED OPTION: %c\n",optopt);
1196 pout(
"=======> %s", extraerror);
1210 char optstr[] = { (char)optchar, 0 };
1211 jerr(
"=======> INVALID ARGUMENT TO -%s: %s\n",
1215 optchar ==
'j' ?
"-json" : optstr), optarg);
1218 pout(
"=======> %s", extraerror);
1240 if (scan_types.size() > 1) {
1243 jerr(
"ERROR: multiple -d TYPE options are only allowed with --scan\n");
1252 jerr(
"\nERROR: smartctl can only run a single test type (or abort) at a time.\n");
1259 if ( (ataopts.smart_selective_args.pending_time || ataopts.smart_selective_args.scan_after_select)
1260 && !ataopts.smart_selective_args.num_spans) {
1263 if (ataopts.smart_selective_args.pending_time)
1264 jerr(
"\nERROR: smartctl -t pending,N must be used with -t select,N-M.\n");
1266 jerr(
"\nERROR: smartctl -t afterselect,(on|off) must be used with -t select,N-M.\n");
1273 switch (ataopts.smart_selftest_type) {
1276 scsiopts.smart_short_selftest =
false;
1277 scsiopts.smart_short_cap_selftest =
true;
1281 scsiopts.smart_extend_selftest =
false;
1282 scsiopts.smart_extend_cap_selftest =
true;
1297 jerr(
"ERROR: smartctl requires a device name as the final command-line argument.\n\n");
1305 jerr(
"ERROR: smartctl takes ONE device name as the final command-line argument.\n");
1306 pout(
"You have provided %d device names:\n",argc-optind);
1307 for (i=0; i<argc-optind; i++)
1308 pout(
"%s\n",argv[optind+i]);
1334 static char buf[1024];
1335 static char * bufnext = buf;
1337 for (
char * p = buf, *q; ; p = q) {
1338 if (!(q = strchr(p,
'\n'))) {
1340 for (bufnext = buf; *p; bufnext++, p++)
1346 static int lineno = 0;
1350 static int outindex = 0;
1351 jglb[
"smartctl"][
"output"][outindex++] = p;
1358 static int errindex = 0;
1368 (is_js_impl ?
'i' :
'u')).c_str()] = p;
1378void pout(
const char *
fmt, ...)
1388 vjpout(
false, 0,
fmt,
ap);
1396void jout(
const char *
fmt, ...)
1406 vjpout(
true, 0,
fmt,
ap);
1414void jinf(
const char *
fmt, ...)
1421 vjpout(
true,
"information",
fmt,
ap);
1425void jwrn(
const char *
fmt, ...)
1432 vjpout(
true,
"warning",
fmt,
ap);
1436void jerr(
const char *
fmt, ...)
1443 vjpout(
true,
"error",
fmt,
ap);
1452 jout(
"%s%s\n", prefix, startup_datetime_buf);
1468 pout(
"An optional SMART command failed: exiting. Remove '-T conservative' option to continue.\n");
1469 throw int(returnvalue);
1476 pout(
"A mandatory SMART command failed: exiting. To continue, add one or more '-T permissive' options.\n");
1477 throw int(returnvalue);
1480 throw std::logic_error(
"failuretest: Unknown type");
1491 pout(
"Warning! %s error: invalid SMART checksum.\n",
string);
1501 switch ( (
int)dev->
is_ata()
1503 | ((
int)dev->
is_nvme() << 2)) {
1504 case 0x1:
return "ATA";
1505 case 0x2:
return "SCSI";
1506 case 0x3:
return "ATA+SCSI";
1507 case 0x4:
return "NVMe";
1508 default:
return "Unknown";
1527 const char * pattern = 0;
1529 if (argv[ai] && argv[ai][0] !=
'-')
1530 pattern = argv[ai++];
1538 pout(
"# scan_smart_devices: %s\n",
smi()->get_errmsg());
1542 for (
unsigned i = 0; i < devlist.
size(); i++) {
1548 dev.
replace ( dev->autodetect_open() );
1554 if (with_open && !dev->is_open()) {
1555 jout(
"# %s -d %s # %s, %s device open failed: %s\n", dev->get_dev_name(),
1556 dev->get_dev_type(), dev->get_info_name(),
1558 jref[
"open_error"] = dev->get_errmsg();
1562 jout(
"%s -d %s", dev->get_dev_name(), dev->get_dev_type());
1566 for (
int j = ai; argv[j]; j++)
1567 jout(
" %s", argv[j]);
1588 const char * type = 0;
1592 bool print_type_only =
false;
1594 int status =
parse_options(argc, argv, type, ataopts, scsiopts, nvmeopts, print_type_only);
1602 time_t now = time(
nullptr);
1604 jglb[
"local_time"] += { {
"time_t", now}, {
"asctime", startup_datetime_buf} };
1607 const char * name = argv[argc-1];
1610 if (!strcmp(name,
"-")) {
1612 if (type || print_type_only) {
1613 pout(
"-d option is not allowed in conjunction with device name \"-\".\n");
1624 jerr(
"%s: %s\n", name,
smi()->get_errmsg());
1628 pout(
"Please specify device type with the -d option.\n");
1633 if (print_type_only)
1635 pout(
"%s: Device of type '%s' [%s] detected\n",
1638 if (dev->is_ata() && ataopts.
powermode>=2 && dev->is_powered_down()) {
1639 jinf(
"Device is in STANDBY (OS) mode, exit(%d)\n", ataopts.
powerexit);
1649 dev.
replace( dev->autodetect_open() );
1653 && oldinfo.
dev_type != dev->get_dev_type() )
1654 pout(
"%s: Device open changed type from '%s' to '%s'\n",
1655 dev->get_info_name(), oldinfo.
dev_type.c_str(), dev->get_dev_type());
1657 if (!dev->is_open()) {
1658 jerr(
"Smartctl open device: %s failed: %s\n", dev->get_info_name(), dev->get_errmsg());
1667 if (print_type_only)
1668 jout(
"%s: Device of type '%s' [%s] opened\n",
1670 else if (dev->is_ata())
1672 else if (dev->is_scsi())
1674 else if (dev->is_nvme())
1678 pout(
"%s: Neither ATA, SCSI nor NVMe device\n", dev->get_info_name());
1689 bool badcode =
false;
1703 jglb[
"smartctl"][
"exit_status"] = status;
1706 catch (
const std::bad_alloc & ) {
1708 printf(
"Smartctl: Out of memory\n");
1711 catch (
const std::exception & ex) {
1713 printf(
"Smartctl: Exception: %s\n", ex.what());
1720 printf(
"Smartctl: Internal Error: %d device object(s) left at exit.\n",
1727 printf(
"Please inform " PACKAGE_BUGREPORT
", including output of smartctl -V.\n");
ata_device * get_parsed_ata_device(smart_interface *intf, const char *dev_name)
bool parse_attribute_def(const char *opt, ata_vendor_attr_defs &defs, ata_vendor_def_prior priority)
std::string create_vendor_attribute_arg_list()
bool parse_firmwarebug_def(const char *opt, firmwarebug_defs &firmwarebugs)
unsigned char ata_debugmode
const char * get_valid_firmwarebug_args()
bool dont_print_serial_number
#define SELECTIVE_SELF_TEST
#define OFFLINE_FULL_SCAN
#define EXTEND_CAPTIVE_SELF_TEST
#define CONVEYANCE_CAPTIVE_SELF_TEST
#define CONVEYANCE_SELF_TEST
#define SHORT_CAPTIVE_SELF_TEST
#define SELECTIVE_CAPTIVE_SELF_TEST
int ataPrintMain(ata_device *device, const ata_print_options &options)
Smart pointer class for device pointers.
device_type * get() const
Return the pointer.
void replace(device_type *dev)
Replace the pointer.
Reference to a JSON element.
Create and print JSON output.
bool has_uint128_output() const
Return true if any 128-bit value has been output.
bool is_enabled() const
Return true if enabled.
void set_verbose(bool yes=true)
Enable/disable extra string output for safe integers also.
void enable(bool yes=true)
Enable/disable JSON output.
void print(FILE *f, const print_options &options) const
Print JSON tree to a file.
List of devices for DEVICESCAN.
smart_device * release(unsigned i)
Base class for all devices.
bool is_scsi() const
Return true if SCSI device.
bool is_nvme() const
Return true if NVMe device.
const char * get_dev_type() const
Get device type.
const char * get_info_name() const
Get informal name.
static int get_num_objects()
Get current number of allocated 'smart_device' objects.
bool is_ata() const
Return true if ATA device.
const char * get_dev_name() const
Get device (path)name.
virtual std::string get_app_examples(const char *appname)
Return example string for program 'appname'.
virtual smart_device * get_smart_device(const char *name, const char *type)
Return device object for device 'name' with some 'type'.
static void init()
Initialize platform interface and register with smi().
virtual std::string get_os_version_str()
Return info string about build host and/or OS version.
virtual bool scan_smart_devices(smart_device_list &devlist, const char *type, const char *pattern=0)
Fill 'devlist' with devices of some 'type' with device names specified by some optional 'pattern'.
virtual std::string get_valid_dev_types_str()
Return valid args for device type option/directive.
std::vector< std::string > smart_devtype_list
List of types for DEVICESCAN.
smart_interface * smi()
Global access to the (usually singleton) smart_interface.
bool init_drive_database(bool use_default_db)
const char * get_drivedb_path_add()
bool read_drive_database(const char *path)
int showmatchingpresets(const char *model, const char *firmware)
unsigned char nvme_debugmode
int nvmePrintMain(nvme_device *device, const nvme_print_options &options)
unsigned char scsi_debugmode
int scsiPrintMain(scsi_device *device, const scsi_print_options &options)
bool failuretest_conservative
static std::string getvalidarglist(int opt)
void jout_startup_datetime(const char *prefix)
unsigned char failuretest_permissive
static int parse_options(int argc, char **argv, const char *&type, ata_print_options &ataopts, scsi_print_options &scsiopts, nvme_print_options &nvmeopts, bool &print_type_only)
int main(int argc, char **argv)
static json::print_options print_as_json_options
static bool print_as_json_output
static void js_device_info(const json::ref &jref, const smart_device *dev)
void checksumwarning(const char *string)
static const char * get_protocol_info(const smart_device *dev)
static checksum_err_mode_t checksum_err_mode
static void printvalidarglistmessage(int opt)
static bool print_as_json_impl
static bool print_as_json_unimpl
static void js_initialize(int argc, char **argv, bool verbose)
void failuretest(failure_type type, int returnvalue)
static int main_worker(int argc, char **argv)
static bool print_as_json
static void UsageSummary()
const char * smartctl_cpp_cvsid
static void printslogan()
const char const char * fmt
bool printing_is_switchable
const char * msg_severity
static void scan_devices(const smart_devtype_list &types, bool with_open, char **argv)
const char const char va_list ap
void void jinf(const char *fmt,...) __attribute_format_printf(1
void void void jwrn(const char *fmt,...) __attribute_format_printf(1
void void void void jerr(const char *fmt,...) __attribute_format_printf(1
void jout(const char *fmt,...) __attribute_format_printf(1
vsnprintf(buf, sizeof(buf), fmt, ap)
void pout(const char *fmt,...)
bool smart_auto_offl_disable
bool sct_wcache_reorder_get
bool smart_auto_save_enable
bool smart_general_values
unsigned sct_erc_writetime
unsigned pending_defects_log
ata_selective_selftest_args smart_selective_args
std::vector< int > devstat_pages
unsigned smart_ext_error_log
unsigned smart_ext_selftest_log
firmwarebug_defs firmwarebugs
unsigned char output_format
int sct_wcache_reorder_set
bool smart_selftest_force
bool smart_selective_selftest_log
ata_vendor_attr_defs attribute_defs
unsigned sct_erc_readtime
std::vector< ata_log_request > log_requests
bool sct_wcache_sct_set_pers
bool sct_wcache_reorder_set_pers
bool smart_auto_offl_enable
bool smart_auto_save_disable
unsigned char smart_selftest_type
unsigned error_log_entries
bool smart_background_log
bool smart_selftest_abort
bool smart_auto_save_disable
bool smart_selftest_force
bool smart_default_selftest
bool smart_short_selftest
bool smart_extend_selftest
bool smart_auto_save_enable
bool scsi_pending_defects
bool general_stats_and_perf
std::string dev_type
Actual device type.
std::string format_version_info(const char *prog_name, int lines)
void dateandtimezoneepoch(char(&buffer)[DATEANDEPOCHLEN], time_t tval)
std::string strprintf(const char *fmt,...)
int split_selective_arg(char *s, uint64_t *start, uint64_t *stop, int *mode)
#define __attribute_format_printf(x, y)
int uint128_to_str_precision_bits()
bool str_starts_with(const char *str, const char *prefix)