4 * Home page of code is: http://smartmontools.sourceforge.net
6 * Copyright (C) 2002-6 Bruce Allen <smartmontools-support@lists.sourceforge.net>
7 * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org>
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2, or (at your option)
14 * You should have received a copy of the GNU General Public License
15 * (for example COPYING); if not, write to the Free
16 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 * This code was originally developed as a Senior Thesis by Michael Cornwell
19 * at the Concurrent Systems Laboratory (now part of the Storage Systems
20 * Research Center), Jack Baskin School of Engineering, University of
21 * California, Santa Cruz. http://ssrc.soe.ucsc.edu/
27 #include <sys/types.h>
32 #ifdef HAVE_GETOPT_LONG
35 #if defined(__FreeBSD_version) && (__FreeBSD_version < 500000)
43 #include "knowndrives.h"
45 #include "scsiprint.h"
49 #ifdef NEED_SOLARIS_ATA_CODE
50 extern const char *os_solaris_ata_s_cvsid
;
52 extern const char *atacmdnames_c_cvsid
, *atacmds_c_cvsid
, *ataprint_c_cvsid
, *knowndrives_c_cvsid
, *os_XXXX_c_cvsid
, *scsicmds_c_cvsid
, *scsiprint_c_cvsid
, *utility_c_cvsid
;
53 const char* smartctl_c_cvsid
="$Id: smartctl.cpp,v 1.156 2006/10/09 11:45:12 guidog Exp $"
54 ATACMDS_H_CVSID ATAPRINT_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID KNOWNDRIVES_H_CVSID SCSICMDS_H_CVSID SCSIPRINT_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID
;
56 // This is a block containing all the "control variables". We declare
57 // this globally in this file, and externally in other files.
58 smartmonctrl
*con
=NULL
;
60 // to hold onto exit code for atexit routine
61 extern int exitstatus
;
67 #ifdef HAVE_GET_OS_VERSION_STR
68 const char * ver
= get_os_version_str();
70 const char * ver
= SMARTMONTOOLS_BUILD_HOST
;
72 pout("smartctl version %s [%s] Copyright (C) 2002-6 Bruce Allen\n", PACKAGE_VERSION
, ver
);
73 pout("Home page is " PACKAGE_HOMEPAGE
"\n\n");
77 void PrintOneCVS(const char *a_cvs_id
){
79 printone(out
,a_cvs_id
);
85 char *configargs
=strlen(SMARTMONTOOLS_CONFIGURE_ARGS
)?SMARTMONTOOLS_CONFIGURE_ARGS
:"[no arguments given]";
87 pout("smartctl comes with ABSOLUTELY NO WARRANTY. This\n");
88 pout("is free software, and you are welcome to redistribute it\n");
89 pout("under the terms of the GNU General Public License Version 2.\n");
90 pout("See http://www.gnu.org for further details.\n\n");
91 pout("CVS version IDs of files used to build this code are:\n");
92 PrintOneCVS(atacmdnames_c_cvsid
);
93 PrintOneCVS(atacmds_c_cvsid
);
94 PrintOneCVS(ataprint_c_cvsid
);
95 PrintOneCVS(knowndrives_c_cvsid
);
96 PrintOneCVS(os_XXXX_c_cvsid
);
97 #ifdef NEED_SOLARIS_ATA_CODE
98 PrintOneCVS(os_solaris_ata_s_cvsid
);
100 PrintOneCVS(scsicmds_c_cvsid
);
101 PrintOneCVS(scsiprint_c_cvsid
);
102 PrintOneCVS(smartctl_c_cvsid
);
103 PrintOneCVS(utility_c_cvsid
);
104 pout("\nsmartmontools release " PACKAGE_VERSION
" dated " SMARTMONTOOLS_RELEASE_DATE
" at " SMARTMONTOOLS_RELEASE_TIME
"\n");
105 pout("smartmontools build host: " SMARTMONTOOLS_BUILD_HOST
"\n");
106 pout("smartmontools build configured: " SMARTMONTOOLS_CONFIGURE_DATE
"\n");
107 pout("smartctl compile dated " __DATE__
" at "__TIME__
"\n");
108 pout("smartmontools configure arguments: %s\n", configargs
);
113 pout("\nUse smartctl -h to get a usage summary\n\n");
117 /* void prints help information for command syntax */
119 printf("Usage: smartctl [options] device\n\n");
120 printf("============================================ SHOW INFORMATION OPTIONS =====\n\n");
121 #ifdef HAVE_GETOPT_LONG
123 " -h, --help, --usage\n"
124 " Display this help and exit\n\n"
125 " -V, --version, --copyright, --license\n"
126 " Print license, copyright, and version information and exit\n\n"
128 " Show identity information for device\n\n"
130 " Show all SMART information for device\n\n"
134 " -h Display this help and exit\n"
135 " -V Print license, copyright, and version information\n"
136 " -i Show identity information for device\n"
137 " -a Show all SMART information for device\n\n"
140 printf("================================== SMARTCTL RUN-TIME BEHAVIOR OPTIONS =====\n\n");
141 #ifdef HAVE_GETOPT_LONG
143 " -q TYPE, --quietmode=TYPE (ATA)\n"
144 " Set smartctl quiet mode to one of: errorsonly, silent\n\n"
145 " -d TYPE, --device=TYPE\n"
146 " Specify device type to one of: ata, scsi, marvell, sat, 3ware,N\n\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, --nocheck=MODE (ATA)\n"
154 " No check if: never, sleep, standby, idle (see man page)\n\n"
158 " -q TYPE Set smartctl quiet mode to one of: errorsonly, silent (ATA)\n"
159 " -d TYPE Specify device type to one of: ata, scsi, 3ware,N\n"
160 " -T TYPE Tolerance: normal, conservative,permissive,verypermissive (ATA\n"
161 " -b TYPE Set action on bad checksum to one of: warn, exit, ignore (ATA)\n"
162 " -r TYPE Report transactions (see man page)\n"
163 " -n MODE No check if: never, sleep, standby, idle (see man page) (ATA)\n\n"
166 printf("============================== DEVICE FEATURE ENABLE/DISABLE COMMANDS =====\n\n");
167 #ifdef HAVE_GETOPT_LONG
169 " -s VALUE, --smart=VALUE\n"
170 " Enable/disable SMART on device (on/off)\n\n"
171 " -o VALUE, --offlineauto=VALUE (ATA)\n"
172 " Enable/disable automatic offline testing on device (on/off)\n\n"
173 " -S VALUE, --saveauto=VALUE (ATA)\n"
174 " Enable/disable Attribute autosave on device (on/off)\n\n"
178 " -s VALUE Enable/disable SMART on device (on/off)\n"
179 " -o VALUE Enable/disable device automatic offline testing (on/off) (ATA)\n"
180 " -S VALUE Enable/disable device Attribute autosave (on/off) (ATA)\n\n"
183 printf("======================================= READ AND DISPLAY DATA OPTIONS =====\n\n");
184 #ifdef HAVE_GETOPT_LONG
187 " Show device SMART health status\n\n"
188 " -c, --capabilities (ATA)\n"
189 " Show device SMART capabilities\n\n"
190 " -A, --attributes \n"
191 " Show device SMART vendor-specific Attributes and values\n\n"
192 " -l TYPE, --log=TYPE\n"
193 " Show device log. TYPE: error, selftest, selective, directory,\n"
195 " -v N,OPTION , --vendorattribute=N,OPTION (ATA)\n"
196 " Set display OPTION for vendor Attribute N (see man page)\n\n"
197 " -F TYPE, --firmwarebug=TYPE (ATA)\n"
198 " Use firmware bug workaround: none, samsung, samsung2\n\n"
199 " -P TYPE, --presets=TYPE (ATA)\n"
200 " Drive-specific presets: use, ignore, show, showall\n\n"
204 " -H Show device SMART health status\n"
205 " -c Show device SMART capabilities (ATA)\n"
206 " -A Show device SMART vendor-specific Attributes and values (ATA)\n"
207 " -l TYPE Show device log. TYPE: error, selftest, selective, directory,\n"
209 " -v N,OPT Set display OPTion for vendor Attribute N (see man page) (ATA)\n"
210 " -F TYPE Use firmware bug workaround: none, samsung, samsung2 (ATA)\n"
211 " -P TYPE Drive-specific presets: use, ignore, show, showall (ATA)\n\n"
214 printf("============================================ DEVICE SELF-TEST OPTIONS =====\n\n");
215 #ifdef HAVE_GETOPT_LONG
217 " -t TEST, --test=TEST\n"
218 " Run test. TEST is: offline short long conveyance select,M-N pending,N afterselect,on afterselect,off\n\n"
220 " Do test in captive mode (along with -t)\n\n"
222 " Abort any non-captive test on device\n\n"
226 " -t TEST Run test. TEST is: offline short long conveyance select,M-N pending,N afterselect,on afterselect,off\n"
227 " -C Do test in captive mode (along with -t)\n"
228 " -X Abort any non-captive test\n\n"
231 print_smartctl_examples();
235 /* Returns a pointer to a static string containing a formatted list of the valid
236 arguments to the option opt or NULL on failure. Note 'v' case different */
237 const char *getvalidarglist(char opt
) {
240 return "errorsonly, silent";
242 return "ata, scsi, marvell, sat, 3ware,N, hpt,L/M/N cciss,N";
244 return "normal, conservative, permissive, verypermissive";
246 return "warn, exit, ignore";
248 return "ioctl[,N], ataioctl[,N], scsiioctl[,N]";
254 return "error, selftest, selective, directory, background";
256 return "use, ignore, show, showall";
258 return "offline, short, long, conveyance, select,M-N, pending,N, afterselect,on, afterselect,off";
260 return "none, samsung, samsung2";
262 return "never, sleep, standby, idle";
269 /* Prints the message "=======> VALID ARGUMENTS ARE: <LIST> \n", where
270 <LIST> is the list of valid arguments for option opt. */
271 void printvalidarglistmessage(char opt
) {
275 s
=create_vendor_attribute_arg_list();
277 s
=(char *)getvalidarglist(opt
);
280 pout("Error whilst constructing argument list for option %c", opt
);
285 pout("=======> VALID ARGUMENTS ARE:\n\thelp\n%s\n<=======\n", s
);
289 // getvalidarglist() might produce a multiline or single line string. We
290 // need to figure out which to get the formatting right.
291 char separator
= strchr(s
, '\n') ? '\n' : ' ';
292 pout("=======> VALID ARGUMENTS ARE:%c%s%c<=======\n", separator
, (char *)s
, separator
);
298 /* Takes command options and sets features to be run */
299 void ParseOpts (int argc
, char** argv
){
303 unsigned char *charp
;
305 extern int optopt
, optind
, opterr
;
306 char extraerror
[256];
307 // Please update getvalidarglist() if you edit shortopts
308 const char *shortopts
= "h?Vq:d:T:b:r:s:o:S:HcAl:iav:P:t:CXF:n:";
309 #ifdef HAVE_GETOPT_LONG
311 // Please update getvalidarglist() if you edit longopts
312 struct option longopts
[] = {
313 { "help", no_argument
, 0, 'h' },
314 { "usage", no_argument
, 0, 'h' },
315 { "version", no_argument
, 0, 'V' },
316 { "copyright", no_argument
, 0, 'V' },
317 { "license", no_argument
, 0, 'V' },
318 { "quietmode", required_argument
, 0, 'q' },
319 { "device", required_argument
, 0, 'd' },
320 { "tolerance", required_argument
, 0, 'T' },
321 { "badsum", required_argument
, 0, 'b' },
322 { "report", required_argument
, 0, 'r' },
323 { "smart", required_argument
, 0, 's' },
324 { "offlineauto", required_argument
, 0, 'o' },
325 { "saveauto", required_argument
, 0, 'S' },
326 { "health", no_argument
, 0, 'H' },
327 { "capabilities", no_argument
, 0, 'c' },
328 { "attributes", no_argument
, 0, 'A' },
329 { "log", required_argument
, 0, 'l' },
330 { "info", no_argument
, 0, 'i' },
331 { "all", no_argument
, 0, 'a' },
332 { "vendorattribute", required_argument
, 0, 'v' },
333 { "presets", required_argument
, 0, 'P' },
334 { "test", required_argument
, 0, 't' },
335 { "captive", no_argument
, 0, 'C' },
336 { "abort", no_argument
, 0, 'X' },
337 { "firmwarebug", required_argument
, 0, 'F' },
338 { "nocheck", required_argument
, 0, 'n' },
343 memset(extraerror
, 0, sizeof(extraerror
));
344 memset(con
,0,sizeof(*con
));
347 badarg
= captive
= FALSE
;
349 // This miserable construction is needed to get emacs to do proper indenting. Sorry!
350 while (-1 != (optchar
=
351 #ifdef HAVE_GETOPT_LONG
352 getopt_long(argc
, argv
, shortopts
, longopts
, NULL
)
354 getopt(argc
, argv
, shortopts
)
359 con
->dont_print
=FALSE
;
365 if (!strcmp(optarg
,"errorsonly")) {
366 con
->printing_switchable
= TRUE
;
367 con
->dont_print
= FALSE
;
368 } else if (!strcmp(optarg
,"silent")) {
369 con
->printing_switchable
= FALSE
;
370 con
->dont_print
= TRUE
;
376 con
->controller_explicit
= 1;
377 if (!strcmp(optarg
,"ata")) {
378 con
->controller_type
= CONTROLLER_ATA
;
379 con
->controller_port
= 0;
380 } else if (!strcmp(optarg
,"scsi")) {
381 con
->controller_type
= CONTROLLER_SCSI
;
382 con
->controller_port
= 0;
383 } else if (!strcmp(optarg
,"marvell")) {
384 con
->controller_type
= CONTROLLER_MARVELL_SATA
;
385 con
->controller_port
= 0;
386 } else if (!strncmp(optarg
, "sat", 3)) {
387 con
->controller_type
= CONTROLLER_SAT
;
388 con
->controller_port
= 0;
389 con
->satpassthrulen
= 0;
390 if (strlen(optarg
) > 3) {
394 cp
= strchr(optarg
, ',');
395 if (cp
&& (1 == sscanf(cp
+ 1, "%d", &k
)) &&
396 ((0 == k
) || (12 == k
) || (16 == k
)))
397 con
->satpassthrulen
= k
;
399 sprintf(extraerror
, "Option '-d sat,<n>' requires <n> to be "
404 } else if (!strncmp(optarg
, "hpt", 3)){
405 unsigned char i
, slash
= 0;
406 con
->hpt_data
[0] = 0;
407 con
->hpt_data
[1] = 0;
408 con
->hpt_data
[2] = 0;
409 con
->controller_type
= CONTROLLER_HPT
;
410 for (i
=4; i
< strlen(optarg
); i
++) {
411 if(optarg
[i
] == '/') {
414 sprintf(extraerror
, "Option '-d hpt,L/M/N' supports 2-3 items\n");
419 else if ((optarg
[i
])>='0' && (optarg
[i
])<='9') {
420 if (con
->hpt_data
[slash
]>1) { /* hpt_data[x] max 19 */
424 con
->hpt_data
[slash
] = con
->hpt_data
[slash
]*10 + optarg
[i
] - '0';
432 sprintf(extraerror
, "Option '-d hpt,L/M/N' requires 2-3 items\n");
434 } else if (badarg
!= TRUE
) {
435 if (con
->hpt_data
[0]==0 || con
->hpt_data
[0]>8){
436 sprintf(extraerror
, "Option '-d hpt,L/M/N' no/invalid controller id L supplied\n");
439 if (con
->hpt_data
[1]==0 || con
->hpt_data
[1]>8){
440 sprintf(extraerror
, "Option '-d hpt,L/M/N' no/invalid channel number M supplied\n");
444 if ( con
->hpt_data
[2]==0 || con
->hpt_data
[2]>15) {
445 sprintf(extraerror
, "Option '-d hpt,L/M/N' no/invalid pmport number N supplied\n");
453 // look for RAID-type device
457 // make a copy of the string to mess with
458 if (!(s
= strdup(optarg
))) {
459 con
->dont_print
= FALSE
;
460 pout("No memory for argument of -d. Exiting...\n");
462 } else if (!strncmp(s
,"3ware,",6)) {
463 if (split_report_arg2(s
, &i
)) {
464 sprintf(extraerror
, "Option -d 3ware,N requires N to be a non-negative integer\n");
466 } else if (i
<0 || i
>15) {
467 sprintf(extraerror
, "Option -d 3ware,N (N=%d) must have 0 <= N <= 15\n", i
);
470 // NOTE: controller_port == disk number + 1
471 con
->controller_type
= CONTROLLER_3WARE
;
472 con
->controller_port
= i
+1;
475 } else if (!strncmp(s
,"cciss,",6)) {
476 if (split_report_arg2(s
, &i
)) {
477 sprintf(extraerror
, "Option -d cciss,N requires N to be a non-negative integer\n");
479 } else if (i
<0 || i
>15) {
480 sprintf(extraerror
, "Option -d cciss,N (N=%d) must have 0 <= N <= 15\n", i
);
483 // NOTE: controller_port == drive number
484 con
->controller_type
= CONTROLLER_CCISS
;
485 con
->controller_port
= i
+1;
493 if (!strcmp(optarg
,"normal")) {
494 con
->conservative
= FALSE
;
496 } else if (!strcmp(optarg
,"conservative")) {
497 con
->conservative
= TRUE
;
498 } else if (!strcmp(optarg
,"permissive")) {
499 if (con
->permissive
<0xff)
501 } else if (!strcmp(optarg
,"verypermissive")) {
502 con
->permissive
=0xff;
508 if (!strcmp(optarg
,"warn")) {
509 con
->checksumfail
= FALSE
;
510 con
->checksumignore
= FALSE
;
511 } else if (!strcmp(optarg
,"exit")) {
512 con
->checksumfail
= TRUE
;
513 con
->checksumignore
= FALSE
;
514 } else if (!strcmp(optarg
,"ignore")) {
515 con
->checksumignore
= TRUE
;
516 con
->checksumfail
= FALSE
;
526 // split_report_arg() may modify its first argument string, so use a
527 // copy of optarg in case we want optarg for an error message.
528 if (!(s
= strdup(optarg
))) {
529 con
->dont_print
= FALSE
;
530 pout("Can't allocate memory to copy argument to -r option"
534 if (split_report_arg(s
, &i
)) {
536 } else if (!strcmp(s
,"ioctl")) {
537 con
->reportataioctl
= con
->reportscsiioctl
= i
;
538 } else if (!strcmp(s
,"ataioctl")) {
539 con
->reportataioctl
= i
;
540 } else if (!strcmp(s
,"scsiioctl")) {
541 con
->reportscsiioctl
= i
;
549 if (!strcmp(optarg
,"on")) {
550 con
->smartenable
= TRUE
;
551 con
->smartdisable
= FALSE
;
552 } else if (!strcmp(optarg
,"off")) {
553 con
->smartdisable
= TRUE
;
554 con
->smartenable
= FALSE
;
560 if (!strcmp(optarg
,"on")) {
561 con
->smartautoofflineenable
= TRUE
;
562 con
->smartautoofflinedisable
= FALSE
;
563 } else if (!strcmp(optarg
,"off")) {
564 con
->smartautoofflinedisable
= TRUE
;
565 con
->smartautoofflineenable
= FALSE
;
571 if (!strcmp(optarg
,"on")) {
572 con
->smartautosaveenable
= TRUE
;
573 con
->smartautosavedisable
= FALSE
;
574 } else if (!strcmp(optarg
,"off")) {
575 con
->smartautosavedisable
= TRUE
;
576 con
->smartautosaveenable
= FALSE
;
582 con
->checksmart
= TRUE
;
585 if (!strcmp(optarg
,"none")) {
586 con
->fixfirmwarebug
= FIX_NONE
;
587 } else if (!strcmp(optarg
,"samsung")) {
588 con
->fixfirmwarebug
= FIX_SAMSUNG
;
589 } else if (!strcmp(optarg
,"samsung2")) {
590 con
->fixfirmwarebug
= FIX_SAMSUNG2
;
596 con
->generalsmartvalues
= TRUE
;
599 con
->smartvendorattrib
= TRUE
;
602 if (!strcmp(optarg
,"error")) {
603 con
->smarterrorlog
= TRUE
;
604 } else if (!strcmp(optarg
,"selftest")) {
605 con
->smartselftestlog
= TRUE
;
606 } else if (!strcmp(optarg
, "selective")) {
607 con
->selectivetestlog
= TRUE
;
608 } else if (!strcmp(optarg
,"directory")) {
609 con
->smartlogdirectory
= TRUE
;
610 } else if (!strcmp(optarg
,"background")) {
611 con
->smartbackgroundlog
= TRUE
;
617 con
->driveinfo
= TRUE
;
620 con
->driveinfo
= TRUE
;
621 con
->checksmart
= TRUE
;
622 con
->generalsmartvalues
= TRUE
;
623 con
->smartvendorattrib
= TRUE
;
624 con
->smarterrorlog
= TRUE
;
625 con
->smartselftestlog
= TRUE
;
626 con
->selectivetestlog
= TRUE
;
627 /* con->smartbackgroundlog = TRUE; */
630 // parse vendor-specific definitions of attributes
631 if (!strcmp(optarg
,"help")) {
633 con
->dont_print
=FALSE
;
635 if (!(s
= create_vendor_attribute_arg_list())) {
636 pout("Insufficient memory to construct argument list\n");
639 pout("The valid arguments to -v are:\n\thelp\n%s\n", s
);
643 charp
=con
->attributedefs
;
645 pout("Fatal internal error in ParseOpts()\n");
648 if (parse_attribute_def(optarg
, &charp
))
652 if (!strcmp(optarg
, "use")) {
653 con
->ignorepresets
= FALSE
;
654 } else if (!strcmp(optarg
, "ignore")) {
655 con
->ignorepresets
= TRUE
;
656 } else if (!strcmp(optarg
, "show")) {
657 con
->showpresets
= TRUE
;
658 } else if (!strcmp(optarg
, "showall")) {
659 if (optind
< argc
) { // -P showall MODEL [FIRMWARE]
660 int cnt
= showmatchingpresets(argv
[optind
], (optind
+1<argc
? argv
[optind
+1] : NULL
));
661 EXIT(cnt
); // report #matches
663 if (showallpresets())
664 EXIT(FAILCMD
); // report regexp syntax error
671 if (!strcmp(optarg
,"offline")) {
672 con
->smartexeoffimmediate
= TRUE
;
673 con
->testcase
= OFFLINE_FULL_SCAN
;
674 } else if (!strcmp(optarg
,"short")) {
675 con
->smartshortselftest
= TRUE
;
676 con
->testcase
= SHORT_SELF_TEST
;
677 } else if (!strcmp(optarg
,"long")) {
678 con
->smartextendselftest
= TRUE
;
679 con
->testcase
= EXTEND_SELF_TEST
;
680 } else if (!strcmp(optarg
,"conveyance")) {
681 con
->smartconveyanceselftest
= TRUE
;
682 con
->testcase
= CONVEYANCE_SELF_TEST
;
683 } else if (!strcmp(optarg
,"afterselect,on")) {
684 // scan remainder of disk after doing selected segments
685 con
->scanafterselect
=2;
686 } else if (!strcmp(optarg
,"afterselect,off")) {
687 // don't scan remainder of disk after doing selected segments
688 con
->scanafterselect
=1;
689 } else if (!strncmp(optarg
,"pending,",strlen("pending,"))) {
690 // parse number of minutes that test should be pending
694 i
=(int)strtol(optarg
+strlen("pending,"), &tailptr
, 10);
695 if (errno
|| *tailptr
!= '\0') {
696 sprintf(extraerror
, "Option -t pending,N requires N to be a non-negative integer\n");
698 } else if (i
<0 || i
>65535) {
699 sprintf(extraerror
, "Option -t pending,N (N=%d) must have 0 <= N <= 65535\n", i
);
702 con
->pendingtime
=i
+1;
704 } else if (!strncmp(optarg
,"select",strlen("select"))) {
705 // parse range of LBAs to test
706 uint64_t start
, stop
;
708 if (split_selective_arg(optarg
, &start
, &stop
)) {
709 sprintf(extraerror
, "Option -t select,M-N must have non-negative integer M and N\n");
712 if (con
->smartselectivenumspans
>= 5 || start
> stop
) {
714 sprintf(extraerror
, "ERROR: Start LBA (%"PRIu64
") > ending LBA (%"PRId64
") in argument \"%s\"\n",
715 start
, stop
, optarg
);
717 sprintf(extraerror
,"ERROR: No more than five selective self-test spans may be"
722 con
->smartselectivespan
[con
->smartselectivenumspans
][0] = start
;
723 con
->smartselectivespan
[con
->smartselectivenumspans
][1] = stop
;
724 con
->smartselectivenumspans
++;
725 con
->testcase
= SELECTIVE_SELF_TEST
;
735 con
->smartselftestabort
= TRUE
;
736 con
->testcase
= ABORT_SELF_TEST
;
739 // skip disk check if in low-power mode
740 if (!strcmp(optarg
, "never"))
741 con
->powermode
= 1; // do not skip, but print mode
742 else if (!strcmp(optarg
, "sleep"))
744 else if (!strcmp(optarg
, "standby"))
746 else if (!strcmp(optarg
, "idle"))
752 con
->dont_print
=FALSE
;
759 con
->dont_print
=FALSE
;
761 #ifdef HAVE_GETOPT_LONG
762 // Point arg to the argument in which this option was found.
763 arg
= argv
[optind
-1];
764 // Check whether the option is a long option that doesn't map to -h.
765 if (arg
[1] == '-' && optchar
!= 'h') {
766 // Iff optopt holds a valid option then argument must be missing.
767 if (optopt
&& (strchr(shortopts
, optopt
) != NULL
)) {
768 pout("=======> ARGUMENT REQUIRED FOR OPTION: %s\n", arg
+2);
769 printvalidarglistmessage(optopt
);
771 pout("=======> UNRECOGNIZED OPTION: %s\n",arg
+2);
773 pout("=======> %s", extraerror
);
779 // Iff optopt holds a valid option then argument must be
780 // missing. Note (BA) this logic seems to fail using Solaris
782 if (strchr(shortopts
, optopt
) != NULL
) {
783 pout("=======> ARGUMENT REQUIRED FOR OPTION: %c\n", optopt
);
784 printvalidarglistmessage(optopt
);
786 pout("=======> UNRECOGNIZED OPTION: %c\n",optopt
);
788 pout("=======> %s", extraerror
);
794 } // closes switch statement to process command-line options
796 // Check to see if option had an unrecognized or incorrect argument.
799 // It would be nice to print the actual option name given by the user
800 // here, but we just print the short form. Please fix this if you know
801 // a clean way to do it.
802 pout("=======> INVALID ARGUMENT TO -%c: %s\n", optchar
, optarg
);
803 printvalidarglistmessage(optchar
);
805 pout("=======> %s", extraerror
);
810 // At this point we have processed all command-line options. If the
811 // print output is switchable, then start with the print output
813 if (con
->printing_switchable
)
814 con
->dont_print
=TRUE
;
816 // error message if user has asked for more than one test
817 if (1<(con
->smartexeoffimmediate
+con
->smartshortselftest
+con
->smartextendselftest
+
818 con
->smartshortcapselftest
+con
->smartextendcapselftest
+con
->smartselftestabort
+ (con
->smartselectivenumspans
>0?1:0))){
819 con
->dont_print
=FALSE
;
821 pout("\nERROR: smartctl can only run a single test type (or abort) at a time.\n");
826 // error message if user has set selective self-test options without
827 // asking for a selective self-test
828 if ((con
->pendingtime
|| con
->scanafterselect
) && !con
->smartselectivenumspans
){
829 con
->dont_print
=FALSE
;
831 if (con
->pendingtime
)
832 pout("\nERROR: smartctl -t pending,N must be used with -t select,N-M.\n");
834 pout("\nERROR: smartctl -t afterselect,(on|off) must be used with -t select,N-M.\n");
839 // If captive option was used, change test type if appropriate.
840 if (captive
&& con
->smartshortselftest
) {
841 con
->smartshortselftest
= FALSE
;
842 con
->smartshortcapselftest
= TRUE
;
843 con
->testcase
= SHORT_CAPTIVE_SELF_TEST
;
844 } else if (captive
&& con
->smartextendselftest
) {
845 con
->smartextendselftest
= FALSE
;
846 con
->smartextendcapselftest
= TRUE
;
847 con
->testcase
= EXTEND_CAPTIVE_SELF_TEST
;
849 else if (captive
&& con
->smartconveyanceselftest
) {
850 con
->smartconveyanceselftest
= FALSE
;
851 con
->smartconveyancecapselftest
= TRUE
;
852 con
->testcase
= CONVEYANCE_CAPTIVE_SELF_TEST
;
854 else if (captive
&& con
->smartselectiveselftest
) {
855 con
->smartselectiveselftest
= FALSE
;
856 con
->smartselectivecapselftest
= TRUE
;
857 con
->testcase
= SELECTIVE_CAPTIVE_SELF_TEST
;
860 // From here on, normal operations...
863 // Warn if the user has provided no device name
865 pout("ERROR: smartctl requires a device name as the final command-line argument.\n\n");
870 // Warn if the user has provided more than one device name
873 pout("ERROR: smartctl takes ONE device name as the final command-line argument.\n");
874 pout("You have provided %d device names:\n",argc
-optind
);
875 for (i
=0; i
<argc
-optind
; i
++)
876 pout("%s\n",argv
[optind
+i
]);
882 // Printing function (controlled by global con->dont_print)
883 // [From GLIBC Manual: Since the prototype doesn't specify types for
884 // optional arguments, in a call to a variadic function the default
885 // argument promotions are performed on the optional argument
886 // values. This means the objects of type char or short int (whether
887 // signed or not) are promoted to either int or unsigned int, as
889 void pout(const char *fmt
, ...){
892 // initialize variable argument list
894 if (con
->dont_print
){
906 // This function is used by utility.cpp to report LOG_CRIT errors.
907 // The smartctl version prints to stdout instead of syslog().
908 void PrintOut(int priority
, const char *fmt
, ...) {
911 // avoid warning message about unused variable from gcc -W: just
912 // change value of local copy.
923 int main (int argc
, char **argv
){
926 smartmonctrl control
;
929 // define control block for external functions
932 // Part input arguments
933 ParseOpts(argc
,argv
);
935 device
= argv
[argc
-1];
937 // If use has specified 3ware controller, determine which interface
938 if (con
->controller_type
== CONTROLLER_3WARE
) {
939 con
->controller_type
=guess_device_type(device
);
940 if (con
->controller_type
!=CONTROLLER_3WARE_9000_CHAR
&& con
->controller_type
!=CONTROLLER_3WARE_678K_CHAR
)
941 con
->controller_type
= CONTROLLER_3WARE_678K
;
944 if (con
->controller_type
== CONTROLLER_UNKNOWN
)
945 con
->controller_type
=guess_device_type(device
);
947 if (con
->controller_type
== CONTROLLER_UNKNOWN
) {
948 pout("Smartctl: please specify device type with the -d option.\n");
953 // set up mode for open() call. SCSI case is:
954 switch (con
->controller_type
) {
955 case CONTROLLER_SCSI
:
959 case CONTROLLER_3WARE_9000_CHAR
:
960 mode
="ATA_3WARE_9000";
962 case CONTROLLER_3WARE_678K_CHAR
:
963 mode
="ATA_3WARE_678K";
965 case CONTROLLER_CCISS
:
973 // open device - SCSI devices are opened (O_RDWR | O_NONBLOCK) so the
974 // scsi generic device can be used (needs write permission for MODE
975 // SELECT command) plus O_NONBLOCK to stop open hanging if media not
976 // present (e.g. with st). Opening is retried O_RDONLY if read-only
977 // media prevents opening O_RDWR (it cannot happen for scsi generic
978 // devices, but it can for the others).
979 fd
= deviceopen(device
, mode
);
982 snprintf(errmsg
,256,"Smartctl open device: %s failed",argv
[argc
-1]);
988 // now call appropriate ATA or SCSI routine
989 switch (con
->controller_type
) {
990 case CONTROLLER_UNKNOWN
:
991 // we should never fall into this branch!
992 pout("Smartctl: please specify device type with the -d option.\n");
996 case CONTROLLER_SCSI
:
997 retval
= scsiPrintMain(fd
);
998 if ((0 == retval
) && (CONTROLLER_SAT
== con
->controller_type
))
999 retval
= ataPrintMain(fd
);
1001 case CONTROLLER_CCISS
:
1002 // route the cciss command through scsiPrintMain.
1003 // cciss pass-throughs will separeate from the SCSI data-path.
1004 retval
= scsiPrintMain(fd
);
1007 retval
= ataPrintMain(fd
);