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.155 2006/09/20 16:17:31 shattered 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";
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)) {
464 } else if (split_report_arg2(s
, &i
)) {
465 sprintf(extraerror
, "Option -d 3ware,N requires N to be a non-negative integer\n");
467 } else if (i
<0 || i
>15) {
468 sprintf(extraerror
, "Option -d 3ware,N (N=%d) must have 0 <= N <= 15\n", i
);
471 // NOTE: controller_port == disk number + 1
472 con
->controller_type
= CONTROLLER_3WARE
;
473 con
->controller_port
= i
+1;
479 if (!strcmp(optarg
,"normal")) {
480 con
->conservative
= FALSE
;
482 } else if (!strcmp(optarg
,"conservative")) {
483 con
->conservative
= TRUE
;
484 } else if (!strcmp(optarg
,"permissive")) {
485 if (con
->permissive
<0xff)
487 } else if (!strcmp(optarg
,"verypermissive")) {
488 con
->permissive
=0xff;
494 if (!strcmp(optarg
,"warn")) {
495 con
->checksumfail
= FALSE
;
496 con
->checksumignore
= FALSE
;
497 } else if (!strcmp(optarg
,"exit")) {
498 con
->checksumfail
= TRUE
;
499 con
->checksumignore
= FALSE
;
500 } else if (!strcmp(optarg
,"ignore")) {
501 con
->checksumignore
= TRUE
;
502 con
->checksumfail
= FALSE
;
512 // split_report_arg() may modify its first argument string, so use a
513 // copy of optarg in case we want optarg for an error message.
514 if (!(s
= strdup(optarg
))) {
515 con
->dont_print
= FALSE
;
516 pout("Can't allocate memory to copy argument to -r option"
520 if (split_report_arg(s
, &i
)) {
522 } else if (!strcmp(s
,"ioctl")) {
523 con
->reportataioctl
= con
->reportscsiioctl
= i
;
524 } else if (!strcmp(s
,"ataioctl")) {
525 con
->reportataioctl
= i
;
526 } else if (!strcmp(s
,"scsiioctl")) {
527 con
->reportscsiioctl
= i
;
535 if (!strcmp(optarg
,"on")) {
536 con
->smartenable
= TRUE
;
537 con
->smartdisable
= FALSE
;
538 } else if (!strcmp(optarg
,"off")) {
539 con
->smartdisable
= TRUE
;
540 con
->smartenable
= FALSE
;
546 if (!strcmp(optarg
,"on")) {
547 con
->smartautoofflineenable
= TRUE
;
548 con
->smartautoofflinedisable
= FALSE
;
549 } else if (!strcmp(optarg
,"off")) {
550 con
->smartautoofflinedisable
= TRUE
;
551 con
->smartautoofflineenable
= FALSE
;
557 if (!strcmp(optarg
,"on")) {
558 con
->smartautosaveenable
= TRUE
;
559 con
->smartautosavedisable
= FALSE
;
560 } else if (!strcmp(optarg
,"off")) {
561 con
->smartautosavedisable
= TRUE
;
562 con
->smartautosaveenable
= FALSE
;
568 con
->checksmart
= TRUE
;
571 if (!strcmp(optarg
,"none")) {
572 con
->fixfirmwarebug
= FIX_NONE
;
573 } else if (!strcmp(optarg
,"samsung")) {
574 con
->fixfirmwarebug
= FIX_SAMSUNG
;
575 } else if (!strcmp(optarg
,"samsung2")) {
576 con
->fixfirmwarebug
= FIX_SAMSUNG2
;
582 con
->generalsmartvalues
= TRUE
;
585 con
->smartvendorattrib
= TRUE
;
588 if (!strcmp(optarg
,"error")) {
589 con
->smarterrorlog
= TRUE
;
590 } else if (!strcmp(optarg
,"selftest")) {
591 con
->smartselftestlog
= TRUE
;
592 } else if (!strcmp(optarg
, "selective")) {
593 con
->selectivetestlog
= TRUE
;
594 } else if (!strcmp(optarg
,"directory")) {
595 con
->smartlogdirectory
= TRUE
;
596 } else if (!strcmp(optarg
,"background")) {
597 con
->smartbackgroundlog
= TRUE
;
603 con
->driveinfo
= TRUE
;
606 con
->driveinfo
= TRUE
;
607 con
->checksmart
= TRUE
;
608 con
->generalsmartvalues
= TRUE
;
609 con
->smartvendorattrib
= TRUE
;
610 con
->smarterrorlog
= TRUE
;
611 con
->smartselftestlog
= TRUE
;
612 con
->selectivetestlog
= TRUE
;
613 /* con->smartbackgroundlog = TRUE; */
616 // parse vendor-specific definitions of attributes
617 if (!strcmp(optarg
,"help")) {
619 con
->dont_print
=FALSE
;
621 if (!(s
= create_vendor_attribute_arg_list())) {
622 pout("Insufficient memory to construct argument list\n");
625 pout("The valid arguments to -v are:\n\thelp\n%s\n", s
);
629 charp
=con
->attributedefs
;
631 pout("Fatal internal error in ParseOpts()\n");
634 if (parse_attribute_def(optarg
, &charp
))
638 if (!strcmp(optarg
, "use")) {
639 con
->ignorepresets
= FALSE
;
640 } else if (!strcmp(optarg
, "ignore")) {
641 con
->ignorepresets
= TRUE
;
642 } else if (!strcmp(optarg
, "show")) {
643 con
->showpresets
= TRUE
;
644 } else if (!strcmp(optarg
, "showall")) {
645 if (optind
< argc
) { // -P showall MODEL [FIRMWARE]
646 int cnt
= showmatchingpresets(argv
[optind
], (optind
+1<argc
? argv
[optind
+1] : NULL
));
647 EXIT(cnt
); // report #matches
649 if (showallpresets())
650 EXIT(FAILCMD
); // report regexp syntax error
657 if (!strcmp(optarg
,"offline")) {
658 con
->smartexeoffimmediate
= TRUE
;
659 con
->testcase
= OFFLINE_FULL_SCAN
;
660 } else if (!strcmp(optarg
,"short")) {
661 con
->smartshortselftest
= TRUE
;
662 con
->testcase
= SHORT_SELF_TEST
;
663 } else if (!strcmp(optarg
,"long")) {
664 con
->smartextendselftest
= TRUE
;
665 con
->testcase
= EXTEND_SELF_TEST
;
666 } else if (!strcmp(optarg
,"conveyance")) {
667 con
->smartconveyanceselftest
= TRUE
;
668 con
->testcase
= CONVEYANCE_SELF_TEST
;
669 } else if (!strcmp(optarg
,"afterselect,on")) {
670 // scan remainder of disk after doing selected segments
671 con
->scanafterselect
=2;
672 } else if (!strcmp(optarg
,"afterselect,off")) {
673 // don't scan remainder of disk after doing selected segments
674 con
->scanafterselect
=1;
675 } else if (!strncmp(optarg
,"pending,",strlen("pending,"))) {
676 // parse number of minutes that test should be pending
680 i
=(int)strtol(optarg
+strlen("pending,"), &tailptr
, 10);
681 if (errno
|| *tailptr
!= '\0') {
682 sprintf(extraerror
, "Option -t pending,N requires N to be a non-negative integer\n");
684 } else if (i
<0 || i
>65535) {
685 sprintf(extraerror
, "Option -t pending,N (N=%d) must have 0 <= N <= 65535\n", i
);
688 con
->pendingtime
=i
+1;
690 } else if (!strncmp(optarg
,"select",strlen("select"))) {
691 // parse range of LBAs to test
692 uint64_t start
, stop
;
694 if (split_selective_arg(optarg
, &start
, &stop
)) {
695 sprintf(extraerror
, "Option -t select,M-N must have non-negative integer M and N\n");
698 if (con
->smartselectivenumspans
>= 5 || start
> stop
) {
700 sprintf(extraerror
, "ERROR: Start LBA (%"PRIu64
") > ending LBA (%"PRId64
") in argument \"%s\"\n",
701 start
, stop
, optarg
);
703 sprintf(extraerror
,"ERROR: No more than five selective self-test spans may be"
708 con
->smartselectivespan
[con
->smartselectivenumspans
][0] = start
;
709 con
->smartselectivespan
[con
->smartselectivenumspans
][1] = stop
;
710 con
->smartselectivenumspans
++;
711 con
->testcase
= SELECTIVE_SELF_TEST
;
721 con
->smartselftestabort
= TRUE
;
722 con
->testcase
= ABORT_SELF_TEST
;
725 // skip disk check if in low-power mode
726 if (!strcmp(optarg
, "never"))
727 con
->powermode
= 1; // do not skip, but print mode
728 else if (!strcmp(optarg
, "sleep"))
730 else if (!strcmp(optarg
, "standby"))
732 else if (!strcmp(optarg
, "idle"))
738 con
->dont_print
=FALSE
;
745 con
->dont_print
=FALSE
;
747 #ifdef HAVE_GETOPT_LONG
748 // Point arg to the argument in which this option was found.
749 arg
= argv
[optind
-1];
750 // Check whether the option is a long option that doesn't map to -h.
751 if (arg
[1] == '-' && optchar
!= 'h') {
752 // Iff optopt holds a valid option then argument must be missing.
753 if (optopt
&& (strchr(shortopts
, optopt
) != NULL
)) {
754 pout("=======> ARGUMENT REQUIRED FOR OPTION: %s\n", arg
+2);
755 printvalidarglistmessage(optopt
);
757 pout("=======> UNRECOGNIZED OPTION: %s\n",arg
+2);
759 pout("=======> %s", extraerror
);
765 // Iff optopt holds a valid option then argument must be
766 // missing. Note (BA) this logic seems to fail using Solaris
768 if (strchr(shortopts
, optopt
) != NULL
) {
769 pout("=======> ARGUMENT REQUIRED FOR OPTION: %c\n", optopt
);
770 printvalidarglistmessage(optopt
);
772 pout("=======> UNRECOGNIZED OPTION: %c\n",optopt
);
774 pout("=======> %s", extraerror
);
780 } // closes switch statement to process command-line options
782 // Check to see if option had an unrecognized or incorrect argument.
785 // It would be nice to print the actual option name given by the user
786 // here, but we just print the short form. Please fix this if you know
787 // a clean way to do it.
788 pout("=======> INVALID ARGUMENT TO -%c: %s\n", optchar
, optarg
);
789 printvalidarglistmessage(optchar
);
791 pout("=======> %s", extraerror
);
796 // At this point we have processed all command-line options. If the
797 // print output is switchable, then start with the print output
799 if (con
->printing_switchable
)
800 con
->dont_print
=TRUE
;
802 // error message if user has asked for more than one test
803 if (1<(con
->smartexeoffimmediate
+con
->smartshortselftest
+con
->smartextendselftest
+
804 con
->smartshortcapselftest
+con
->smartextendcapselftest
+con
->smartselftestabort
+ (con
->smartselectivenumspans
>0?1:0))){
805 con
->dont_print
=FALSE
;
807 pout("\nERROR: smartctl can only run a single test type (or abort) at a time.\n");
812 // error message if user has set selective self-test options without
813 // asking for a selective self-test
814 if ((con
->pendingtime
|| con
->scanafterselect
) && !con
->smartselectivenumspans
){
815 con
->dont_print
=FALSE
;
817 if (con
->pendingtime
)
818 pout("\nERROR: smartctl -t pending,N must be used with -t select,N-M.\n");
820 pout("\nERROR: smartctl -t afterselect,(on|off) must be used with -t select,N-M.\n");
825 // If captive option was used, change test type if appropriate.
826 if (captive
&& con
->smartshortselftest
) {
827 con
->smartshortselftest
= FALSE
;
828 con
->smartshortcapselftest
= TRUE
;
829 con
->testcase
= SHORT_CAPTIVE_SELF_TEST
;
830 } else if (captive
&& con
->smartextendselftest
) {
831 con
->smartextendselftest
= FALSE
;
832 con
->smartextendcapselftest
= TRUE
;
833 con
->testcase
= EXTEND_CAPTIVE_SELF_TEST
;
835 else if (captive
&& con
->smartconveyanceselftest
) {
836 con
->smartconveyanceselftest
= FALSE
;
837 con
->smartconveyancecapselftest
= TRUE
;
838 con
->testcase
= CONVEYANCE_CAPTIVE_SELF_TEST
;
840 else if (captive
&& con
->smartselectiveselftest
) {
841 con
->smartselectiveselftest
= FALSE
;
842 con
->smartselectivecapselftest
= TRUE
;
843 con
->testcase
= SELECTIVE_CAPTIVE_SELF_TEST
;
846 // From here on, normal operations...
849 // Warn if the user has provided no device name
851 pout("ERROR: smartctl requires a device name as the final command-line argument.\n\n");
856 // Warn if the user has provided more than one device name
859 pout("ERROR: smartctl takes ONE device name as the final command-line argument.\n");
860 pout("You have provided %d device names:\n",argc
-optind
);
861 for (i
=0; i
<argc
-optind
; i
++)
862 pout("%s\n",argv
[optind
+i
]);
868 // Printing function (controlled by global con->dont_print)
869 // [From GLIBC Manual: Since the prototype doesn't specify types for
870 // optional arguments, in a call to a variadic function the default
871 // argument promotions are performed on the optional argument
872 // values. This means the objects of type char or short int (whether
873 // signed or not) are promoted to either int or unsigned int, as
875 void pout(const char *fmt
, ...){
878 // initialize variable argument list
880 if (con
->dont_print
){
892 // This function is used by utility.cpp to report LOG_CRIT errors.
893 // The smartctl version prints to stdout instead of syslog().
894 void PrintOut(int priority
, const char *fmt
, ...) {
897 // avoid warning message about unused variable from gcc -W: just
898 // change value of local copy.
909 int main (int argc
, char **argv
){
912 smartmonctrl control
;
915 // define control block for external functions
918 // Part input arguments
919 ParseOpts(argc
,argv
);
921 device
= argv
[argc
-1];
923 // If use has specified 3ware controller, determine which interface
924 if (con
->controller_type
== CONTROLLER_3WARE
) {
925 con
->controller_type
=guess_device_type(device
);
926 if (con
->controller_type
!=CONTROLLER_3WARE_9000_CHAR
&& con
->controller_type
!=CONTROLLER_3WARE_678K_CHAR
)
927 con
->controller_type
= CONTROLLER_3WARE_678K
;
930 if (con
->controller_type
== CONTROLLER_UNKNOWN
)
931 con
->controller_type
=guess_device_type(device
);
933 if (con
->controller_type
== CONTROLLER_UNKNOWN
) {
934 pout("Smartctl: please specify device type with the -d option.\n");
939 // set up mode for open() call. SCSI case is:
940 switch (con
->controller_type
) {
941 case CONTROLLER_SCSI
:
945 case CONTROLLER_3WARE_9000_CHAR
:
946 mode
="ATA_3WARE_9000";
948 case CONTROLLER_3WARE_678K_CHAR
:
949 mode
="ATA_3WARE_678K";
956 // open device - SCSI devices are opened (O_RDWR | O_NONBLOCK) so the
957 // scsi generic device can be used (needs write permission for MODE
958 // SELECT command) plus O_NONBLOCK to stop open hanging if media not
959 // present (e.g. with st). Opening is retried O_RDONLY if read-only
960 // media prevents opening O_RDWR (it cannot happen for scsi generic
961 // devices, but it can for the others).
962 fd
= deviceopen(device
, mode
);
965 snprintf(errmsg
,256,"Smartctl open device: %s failed",argv
[argc
-1]);
971 // now call appropriate ATA or SCSI routine
972 switch (con
->controller_type
) {
973 case CONTROLLER_UNKNOWN
:
974 // we should never fall into this branch!
975 pout("Smartctl: please specify device type with the -d option.\n");
979 case CONTROLLER_SCSI
:
980 retval
= scsiPrintMain(fd
);
981 if ((0 == retval
) && (CONTROLLER_SAT
== con
->controller_type
))
982 retval
= ataPrintMain(fd
);
985 retval
= ataPrintMain(fd
);