4 * Home page of code is: http://smartmontools.sourceforge.net
6 * Copyright (C) 2002-7 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)
39 #if defined(__QNXNTO__)
48 #include "knowndrives.h"
50 #include "scsiprint.h"
54 #ifdef NEED_SOLARIS_ATA_CODE
55 extern const char *os_solaris_ata_s_cvsid
;
57 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
;
58 const char* smartctl_c_cvsid
="$Id: smartctl.cpp,v 1.168 2007/11/13 14:53:27 jhering Exp $"
59 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
;
61 // This is a block containing all the "control variables". We declare
62 // this globally in this file, and externally in other files.
63 smartmonctrl
*con
=NULL
;
65 // to hold onto exit code for atexit routine
66 extern int exitstatus
;
72 #ifdef HAVE_GET_OS_VERSION_STR
73 const char * ver
= get_os_version_str();
75 const char * ver
= SMARTMONTOOLS_BUILD_HOST
;
77 pout("smartctl version %s [%s] Copyright (C) 2002-7 Bruce Allen\n", PACKAGE_VERSION
, ver
);
78 pout("Home page is " PACKAGE_HOMEPAGE
"\n\n");
82 void PrintOneCVS(const char *a_cvs_id
){
84 printone(out
,a_cvs_id
);
90 const char *configargs
=strlen(SMARTMONTOOLS_CONFIGURE_ARGS
)?SMARTMONTOOLS_CONFIGURE_ARGS
:"[no arguments given]";
92 pout("smartctl comes with ABSOLUTELY NO WARRANTY. This\n");
93 pout("is free software, and you are welcome to redistribute it\n");
94 pout("under the terms of the GNU General Public License Version 2.\n");
95 pout("See http://www.gnu.org for further details.\n\n");
96 pout("CVS version IDs of files used to build this code are:\n");
97 PrintOneCVS(atacmdnames_c_cvsid
);
98 PrintOneCVS(atacmds_c_cvsid
);
99 PrintOneCVS(ataprint_c_cvsid
);
100 PrintOneCVS(knowndrives_c_cvsid
);
101 PrintOneCVS(os_XXXX_c_cvsid
);
102 #ifdef NEED_SOLARIS_ATA_CODE
103 PrintOneCVS(os_solaris_ata_s_cvsid
);
105 PrintOneCVS(scsicmds_c_cvsid
);
106 PrintOneCVS(scsiprint_c_cvsid
);
107 PrintOneCVS(smartctl_c_cvsid
);
108 PrintOneCVS(utility_c_cvsid
);
109 pout("\nsmartmontools release " PACKAGE_VERSION
" dated " SMARTMONTOOLS_RELEASE_DATE
" at " SMARTMONTOOLS_RELEASE_TIME
"\n");
110 pout("smartmontools build host: " SMARTMONTOOLS_BUILD_HOST
"\n");
111 pout("smartmontools build configured: " SMARTMONTOOLS_CONFIGURE_DATE
"\n");
112 pout("smartctl compile dated " __DATE__
" at "__TIME__
"\n");
113 pout("smartmontools configure arguments: %s\n", configargs
);
118 pout("\nUse smartctl -h to get a usage summary\n\n");
122 /* void prints help information for command syntax */
124 printf("Usage: smartctl [options] device\n\n");
125 printf("============================================ SHOW INFORMATION OPTIONS =====\n\n");
126 #ifdef HAVE_GETOPT_LONG
128 " -h, --help, --usage\n"
129 " Display this help and exit\n\n"
130 " -V, --version, --copyright, --license\n"
131 " Print license, copyright, and version information and exit\n\n"
133 " Show identity information for device\n\n"
135 " Show all SMART information for device\n\n"
139 " -h Display this help and exit\n"
140 " -V Print license, copyright, and version information\n"
141 " -i Show identity information for device\n"
142 " -a Show all SMART information for device\n\n"
145 printf("================================== SMARTCTL RUN-TIME BEHAVIOR OPTIONS =====\n\n");
146 #ifdef HAVE_GETOPT_LONG
148 " -q TYPE, --quietmode=TYPE (ATA)\n"
149 " Set smartctl quiet mode to one of: errorsonly, silent, noserial\n\n"
150 " -d TYPE, --device=TYPE\n"
151 " Specify device type to one of: ata, scsi, marvell, sat, 3ware,N\n\n"
152 " -T TYPE, --tolerance=TYPE (ATA)\n"
153 " Tolerance: normal, conservative, permissive, verypermissive\n\n"
154 " -b TYPE, --badsum=TYPE (ATA)\n"
155 " Set action on bad checksum to one of: warn, exit, ignore\n\n"
156 " -r TYPE, --report=TYPE\n"
157 " Report transactions (see man page)\n\n"
158 " -n MODE, --nocheck=MODE (ATA)\n"
159 " No check if: never, sleep, standby, idle (see man page)\n\n"
163 " -q TYPE Set smartctl quiet mode to one of: errorsonly, silent, (ATA)\n"
165 " -d TYPE Specify device type to one of: ata, scsi, 3ware,N\n"
166 " -T TYPE Tolerance: normal, conservative,permissive,verypermissive (ATA)\n"
167 " -b TYPE Set action on bad checksum to one of: warn, exit, ignore (ATA)\n"
168 " -r TYPE Report transactions (see man page)\n"
169 " -n MODE No check if: never, sleep, standby, idle (see man page) (ATA)\n\n"
172 printf("============================== DEVICE FEATURE ENABLE/DISABLE COMMANDS =====\n\n");
173 #ifdef HAVE_GETOPT_LONG
175 " -s VALUE, --smart=VALUE\n"
176 " Enable/disable SMART on device (on/off)\n\n"
177 " -o VALUE, --offlineauto=VALUE (ATA)\n"
178 " Enable/disable automatic offline testing on device (on/off)\n\n"
179 " -S VALUE, --saveauto=VALUE (ATA)\n"
180 " Enable/disable Attribute autosave on device (on/off)\n\n"
184 " -s VALUE Enable/disable SMART on device (on/off)\n"
185 " -o VALUE Enable/disable device automatic offline testing (on/off) (ATA)\n"
186 " -S VALUE Enable/disable device Attribute autosave (on/off) (ATA)\n\n"
189 printf("======================================= READ AND DISPLAY DATA OPTIONS =====\n\n");
190 #ifdef HAVE_GETOPT_LONG
193 " Show device SMART health status\n\n"
194 " -c, --capabilities (ATA)\n"
195 " Show device SMART capabilities\n\n"
196 " -A, --attributes \n"
197 " Show device SMART vendor-specific Attributes and values\n\n"
198 " -l TYPE, --log=TYPE\n"
199 " Show device log. TYPE: error, selftest, selective, directory,\n"
200 " background, scttemp[sts,hist]\n\n"
201 " -v N,OPTION , --vendorattribute=N,OPTION (ATA)\n"
202 " Set display OPTION for vendor Attribute N (see man page)\n\n"
203 " -F TYPE, --firmwarebug=TYPE (ATA)\n"
204 " Use firmware bug workaround: none, samsung, samsung2,\n"
205 " samsung3, swapid\n\n"
206 " -P TYPE, --presets=TYPE (ATA)\n"
207 " Drive-specific presets: use, ignore, show, showall\n\n"
211 " -H Show device SMART health status\n"
212 " -c Show device SMART capabilities (ATA)\n"
213 " -A Show device SMART vendor-specific Attributes and values (ATA)\n"
214 " -l TYPE Show device log. TYPE: error, selftest, selective, directory,\n"
215 " background, scttemp[sts,hist]\n"
216 " -v N,OPT Set display OPTion for vendor Attribute N (see man page) (ATA)\n"
217 " -F TYPE Use firmware bug workaround: none, samsung, samsung2, (ATA)\n"
218 " samsung3, swapid\n"
219 " -P TYPE Drive-specific presets: use, ignore, show, showall (ATA)\n\n"
222 printf("============================================ DEVICE SELF-TEST OPTIONS =====\n\n");
223 #ifdef HAVE_GETOPT_LONG
225 " -t TEST, --test=TEST\n"
226 " Run test. TEST: offline short long conveyance select,M-N\n"
227 " pending,N afterselect,[on|off] scttempint,N[,p]\n\n"
229 " Do test in captive mode (along with -t)\n\n"
231 " Abort any non-captive test on device\n\n"
235 " -t TEST Run test. TEST: offline short long conveyance select,M-N\n"
236 " pending,N afterselect,[on|off] scttempint,N[,p]\n"
237 " -C Do test in captive mode (along with -t)\n"
238 " -X Abort any non-captive test\n\n"
241 print_smartctl_examples();
245 /* Returns a pointer to a static string containing a formatted list of the valid
246 arguments to the option opt or NULL on failure. Note 'v' case different */
247 const char *getvalidarglist(char opt
) {
250 return "errorsonly, silent, noserial";
252 return "ata, scsi, marvell, sat, 3ware,N, hpt,L/M/N cciss,N";
254 return "normal, conservative, permissive, verypermissive";
256 return "warn, exit, ignore";
258 return "ioctl[,N], ataioctl[,N], scsiioctl[,N]";
264 return "error, selftest, selective, directory, background, scttemp[sts|hist]";
266 return "use, ignore, show, showall";
268 return "offline, short, long, conveyance, select,M-N, pending,N, afterselect,[on|off], scttempint,N[,p]";
270 return "none, samsung, samsung2, samsung3, swapid";
272 return "never, sleep, standby, idle";
279 /* Prints the message "=======> VALID ARGUMENTS ARE: <LIST> \n", where
280 <LIST> is the list of valid arguments for option opt. */
281 void printvalidarglistmessage(char opt
) {
285 s
=create_vendor_attribute_arg_list();
287 s
=(char *)getvalidarglist(opt
);
290 pout("Error whilst constructing argument list for option %c", opt
);
295 pout("=======> VALID ARGUMENTS ARE:\n\thelp\n%s\n<=======\n", s
);
299 // getvalidarglist() might produce a multiline or single line string. We
300 // need to figure out which to get the formatting right.
301 char separator
= strchr(s
, '\n') ? '\n' : ' ';
302 pout("=======> VALID ARGUMENTS ARE:%c%s%c<=======\n", separator
, (char *)s
, separator
);
308 /* Takes command options and sets features to be run */
309 void ParseOpts (int argc
, char** argv
){
313 unsigned char *charp
;
315 extern int optopt
, optind
, opterr
;
316 char extraerror
[256];
317 // Please update getvalidarglist() if you edit shortopts
318 const char *shortopts
= "h?Vq:d:T:b:r:s:o:S:HcAl:iav:P:t:CXF:n:";
319 #ifdef HAVE_GETOPT_LONG
321 // Please update getvalidarglist() if you edit longopts
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, 's' },
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 { "vendorattribute", required_argument
, 0, 'v' },
343 { "presets", required_argument
, 0, 'P' },
344 { "test", required_argument
, 0, 't' },
345 { "captive", no_argument
, 0, 'C' },
346 { "abort", no_argument
, 0, 'X' },
347 { "firmwarebug", required_argument
, 0, 'F' },
348 { "nocheck", required_argument
, 0, 'n' },
353 memset(extraerror
, 0, sizeof(extraerror
));
354 memset(con
,0,sizeof(*con
));
357 badarg
= captive
= FALSE
;
359 // This miserable construction is needed to get emacs to do proper indenting. Sorry!
360 while (-1 != (optchar
=
361 #ifdef HAVE_GETOPT_LONG
362 getopt_long(argc
, argv
, shortopts
, longopts
, NULL
)
364 getopt(argc
, argv
, shortopts
)
369 con
->dont_print
=FALSE
;
375 if (!strcmp(optarg
,"errorsonly")) {
376 con
->printing_switchable
= TRUE
;
377 con
->dont_print
= FALSE
;
378 } else if (!strcmp(optarg
,"silent")) {
379 con
->printing_switchable
= FALSE
;
380 con
->dont_print
= TRUE
;
381 } else if (!strcmp(optarg
,"noserial")) {
382 con
->dont_print_serial
= TRUE
;
388 con
->controller_explicit
= 1;
389 if (!strcmp(optarg
,"ata")) {
390 con
->controller_type
= CONTROLLER_ATA
;
391 con
->controller_port
= 0;
392 } else if (!strcmp(optarg
,"scsi")) {
393 con
->controller_type
= CONTROLLER_SCSI
;
394 con
->controller_port
= 0;
395 } else if (!strcmp(optarg
,"marvell")) {
396 con
->controller_type
= CONTROLLER_MARVELL_SATA
;
397 con
->controller_port
= 0;
398 } else if (!strncmp(optarg
, "sat", 3)) {
399 con
->controller_type
= CONTROLLER_SAT
;
400 con
->controller_port
= 0;
401 con
->satpassthrulen
= 0;
402 if (strlen(optarg
) > 3) {
406 cp
= strchr(optarg
, ',');
407 if (cp
&& (1 == sscanf(cp
+ 1, "%d", &k
)) &&
408 ((0 == k
) || (12 == k
) || (16 == k
)))
409 con
->satpassthrulen
= k
;
411 sprintf(extraerror
, "Option '-d sat,<n>' requires <n> to be "
416 } else if (!strncmp(optarg
, "hpt", 3)){
417 unsigned char i
, slash
= 0;
418 con
->hpt_data
[0] = 0;
419 con
->hpt_data
[1] = 0;
420 con
->hpt_data
[2] = 0;
421 con
->controller_type
= CONTROLLER_HPT
;
422 for (i
=4; i
< strlen(optarg
); i
++) {
423 if(optarg
[i
] == '/') {
426 sprintf(extraerror
, "Option '-d hpt,L/M/N' supports 2-3 items\n");
431 else if ((optarg
[i
])>='0' && (optarg
[i
])<='9') {
432 if (con
->hpt_data
[slash
]>1) { /* hpt_data[x] max 19 */
436 con
->hpt_data
[slash
] = con
->hpt_data
[slash
]*10 + optarg
[i
] - '0';
444 sprintf(extraerror
, "Option '-d hpt,L/M/N' requires 2-3 items\n");
446 } else if (badarg
!= TRUE
) {
447 if (con
->hpt_data
[0]==0 || con
->hpt_data
[0]>8){
448 sprintf(extraerror
, "Option '-d hpt,L/M/N' no/invalid controller id L supplied\n");
451 if (con
->hpt_data
[1]==0 || con
->hpt_data
[1]>8){
452 sprintf(extraerror
, "Option '-d hpt,L/M/N' no/invalid channel number M supplied\n");
456 if ( con
->hpt_data
[2]==0 || con
->hpt_data
[2]>15) {
457 sprintf(extraerror
, "Option '-d hpt,L/M/N' no/invalid pmport number N supplied\n");
465 // look for RAID-type device
469 // make a copy of the string to mess with
470 if (!(s
= strdup(optarg
))) {
471 con
->dont_print
= FALSE
;
472 pout("No memory for argument of -d. Exiting...\n");
474 } else if (!strncmp(s
,"3ware,",6)) {
475 if (split_report_arg2(s
, &i
)) {
476 sprintf(extraerror
, "Option -d 3ware,N requires N to be a non-negative integer\n");
478 } else if (i
<0 || i
>31) {
479 sprintf(extraerror
, "Option -d 3ware,N (N=%d) must have 0 <= N <= 31\n", i
);
482 // NOTE: controller_port == disk number + 1
483 con
->controller_type
= CONTROLLER_3WARE
;
484 con
->controller_port
= i
+1;
487 } else if (!strncmp(s
,"cciss,",6)) {
488 if (split_report_arg2(s
, &i
)) {
489 sprintf(extraerror
, "Option -d cciss,N requires N to be a non-negative integer\n");
491 } else if (i
<0 || i
>127) {
492 sprintf(extraerror
, "Option -d cciss,N (N=%d) must have 0 <= N <= 127\n", i
);
495 // NOTE: controller_port == drive number
496 con
->controller_type
= CONTROLLER_CCISS
;
497 con
->controller_port
= i
+1;
505 if (!strcmp(optarg
,"normal")) {
506 con
->conservative
= FALSE
;
508 } else if (!strcmp(optarg
,"conservative")) {
509 con
->conservative
= TRUE
;
510 } else if (!strcmp(optarg
,"permissive")) {
511 if (con
->permissive
<0xff)
513 } else if (!strcmp(optarg
,"verypermissive")) {
514 con
->permissive
=0xff;
520 if (!strcmp(optarg
,"warn")) {
521 con
->checksumfail
= FALSE
;
522 con
->checksumignore
= FALSE
;
523 } else if (!strcmp(optarg
,"exit")) {
524 con
->checksumfail
= TRUE
;
525 con
->checksumignore
= FALSE
;
526 } else if (!strcmp(optarg
,"ignore")) {
527 con
->checksumignore
= TRUE
;
528 con
->checksumfail
= FALSE
;
538 // split_report_arg() may modify its first argument string, so use a
539 // copy of optarg in case we want optarg for an error message.
540 if (!(s
= strdup(optarg
))) {
541 con
->dont_print
= FALSE
;
542 pout("Can't allocate memory to copy argument to -r option"
546 if (split_report_arg(s
, &i
)) {
548 } else if (!strcmp(s
,"ioctl")) {
549 con
->reportataioctl
= con
->reportscsiioctl
= i
;
550 } else if (!strcmp(s
,"ataioctl")) {
551 con
->reportataioctl
= i
;
552 } else if (!strcmp(s
,"scsiioctl")) {
553 con
->reportscsiioctl
= i
;
561 if (!strcmp(optarg
,"on")) {
562 con
->smartenable
= TRUE
;
563 con
->smartdisable
= FALSE
;
564 } else if (!strcmp(optarg
,"off")) {
565 con
->smartdisable
= TRUE
;
566 con
->smartenable
= FALSE
;
572 if (!strcmp(optarg
,"on")) {
573 con
->smartautoofflineenable
= TRUE
;
574 con
->smartautoofflinedisable
= FALSE
;
575 } else if (!strcmp(optarg
,"off")) {
576 con
->smartautoofflinedisable
= TRUE
;
577 con
->smartautoofflineenable
= FALSE
;
583 if (!strcmp(optarg
,"on")) {
584 con
->smartautosaveenable
= TRUE
;
585 con
->smartautosavedisable
= FALSE
;
586 } else if (!strcmp(optarg
,"off")) {
587 con
->smartautosavedisable
= TRUE
;
588 con
->smartautosaveenable
= FALSE
;
594 con
->checksmart
= TRUE
;
597 if (!strcmp(optarg
,"none")) {
598 con
->fixfirmwarebug
= FIX_NONE
;
599 } else if (!strcmp(optarg
,"samsung")) {
600 con
->fixfirmwarebug
= FIX_SAMSUNG
;
601 } else if (!strcmp(optarg
,"samsung2")) {
602 con
->fixfirmwarebug
= FIX_SAMSUNG2
;
603 } else if (!strcmp(optarg
,"samsung3")) {
604 con
->fixfirmwarebug
= FIX_SAMSUNG3
;
605 } else if (!strcmp(optarg
,"swapid")) {
606 con
->fixswappedid
= TRUE
;
612 con
->generalsmartvalues
= TRUE
;
615 con
->smartvendorattrib
= TRUE
;
618 if (!strcmp(optarg
,"error")) {
619 con
->smarterrorlog
= TRUE
;
620 } else if (!strcmp(optarg
,"selftest")) {
621 con
->smartselftestlog
= TRUE
;
622 } else if (!strcmp(optarg
, "selective")) {
623 con
->selectivetestlog
= TRUE
;
624 } else if (!strcmp(optarg
,"directory")) {
625 con
->smartlogdirectory
= TRUE
;
626 } else if (!strcmp(optarg
,"background")) {
627 con
->smartbackgroundlog
= TRUE
;
628 } else if (!strcmp(optarg
,"scttemp")) {
629 con
->scttempsts
= con
->scttemphist
= TRUE
;
630 } else if (!strcmp(optarg
,"scttempsts")) {
631 con
->scttempsts
= TRUE
;
632 } else if (!strcmp(optarg
,"scttemphist")) {
633 con
->scttemphist
= TRUE
;
639 con
->driveinfo
= TRUE
;
642 con
->driveinfo
= TRUE
;
643 con
->checksmart
= TRUE
;
644 con
->generalsmartvalues
= TRUE
;
645 con
->smartvendorattrib
= TRUE
;
646 con
->smarterrorlog
= TRUE
;
647 con
->smartselftestlog
= TRUE
;
648 con
->selectivetestlog
= TRUE
;
649 /* con->smartbackgroundlog = TRUE; */
652 // parse vendor-specific definitions of attributes
653 if (!strcmp(optarg
,"help")) {
655 con
->dont_print
=FALSE
;
657 if (!(s
= create_vendor_attribute_arg_list())) {
658 pout("Insufficient memory to construct argument list\n");
661 pout("The valid arguments to -v are:\n\thelp\n%s\n", s
);
665 charp
=con
->attributedefs
;
667 pout("Fatal internal error in ParseOpts()\n");
670 if (parse_attribute_def(optarg
, &charp
))
674 if (!strcmp(optarg
, "use")) {
675 con
->ignorepresets
= FALSE
;
676 } else if (!strcmp(optarg
, "ignore")) {
677 con
->ignorepresets
= TRUE
;
678 } else if (!strcmp(optarg
, "show")) {
679 con
->showpresets
= TRUE
;
680 } else if (!strcmp(optarg
, "showall")) {
681 if (optind
< argc
) { // -P showall MODEL [FIRMWARE]
682 int cnt
= showmatchingpresets(argv
[optind
], (optind
+1<argc
? argv
[optind
+1] : NULL
));
683 EXIT(cnt
); // report #matches
685 if (showallpresets())
686 EXIT(FAILCMD
); // report regexp syntax error
693 if (!strcmp(optarg
,"offline")) {
694 con
->smartexeoffimmediate
= TRUE
;
695 con
->testcase
= OFFLINE_FULL_SCAN
;
696 } else if (!strcmp(optarg
,"short")) {
697 con
->smartshortselftest
= TRUE
;
698 con
->testcase
= SHORT_SELF_TEST
;
699 } else if (!strcmp(optarg
,"long")) {
700 con
->smartextendselftest
= TRUE
;
701 con
->testcase
= EXTEND_SELF_TEST
;
702 } else if (!strcmp(optarg
,"conveyance")) {
703 con
->smartconveyanceselftest
= TRUE
;
704 con
->testcase
= CONVEYANCE_SELF_TEST
;
705 } else if (!strcmp(optarg
,"afterselect,on")) {
706 // scan remainder of disk after doing selected segments
707 con
->scanafterselect
=2;
708 } else if (!strcmp(optarg
,"afterselect,off")) {
709 // don't scan remainder of disk after doing selected segments
710 con
->scanafterselect
=1;
711 } else if (!strncmp(optarg
,"pending,",strlen("pending,"))) {
712 // parse number of minutes that test should be pending
716 i
=(int)strtol(optarg
+strlen("pending,"), &tailptr
, 10);
717 if (errno
|| *tailptr
!= '\0') {
718 sprintf(extraerror
, "Option -t pending,N requires N to be a non-negative integer\n");
720 } else if (i
<0 || i
>65535) {
721 sprintf(extraerror
, "Option -t pending,N (N=%d) must have 0 <= N <= 65535\n", i
);
724 con
->pendingtime
=i
+1;
726 } else if (!strncmp(optarg
,"select",strlen("select"))) {
727 // parse range of LBAs to test
728 uint64_t start
, stop
; int mode
;
729 if (split_selective_arg(optarg
, &start
, &stop
, &mode
)) {
730 sprintf(extraerror
, "Option -t select,M-N must have non-negative integer M and N\n");
733 if (con
->smartselectivenumspans
>= 5 || start
> stop
) {
735 sprintf(extraerror
, "ERROR: Start LBA (%"PRIu64
") > ending LBA (%"PRId64
") in argument \"%s\"\n",
736 start
, stop
, optarg
);
738 sprintf(extraerror
,"ERROR: No more than five selective self-test spans may be"
743 con
->smartselectivespan
[con
->smartselectivenumspans
][0] = start
;
744 con
->smartselectivespan
[con
->smartselectivenumspans
][1] = stop
;
745 con
->smartselectivemode
[con
->smartselectivenumspans
] = mode
;
746 con
->smartselectivenumspans
++;
747 con
->testcase
= SELECTIVE_SELF_TEST
;
749 } else if (!strncmp(optarg
, "scttempint,", sizeof("scstempint,")-1)) {
750 unsigned interval
= 0; int n1
= -1, n2
= -1, len
= strlen(optarg
);
751 if (!( sscanf(optarg
,"scttempint,%u%n,p%n", &interval
, &n1
, &n2
) == 1
752 && 0 < interval
&& interval
<= 0xffff && (n1
== len
|| n2
== len
))) {
753 strcpy(extraerror
, "Option -t scttempint,N[,p] must have positive integer N\n");
756 con
->scttempint
= interval
;
757 con
->scttempintp
= (n2
== len
);
766 con
->smartselftestabort
= TRUE
;
767 con
->testcase
= ABORT_SELF_TEST
;
770 // skip disk check if in low-power mode
771 if (!strcmp(optarg
, "never"))
772 con
->powermode
= 1; // do not skip, but print mode
773 else if (!strcmp(optarg
, "sleep"))
775 else if (!strcmp(optarg
, "standby"))
777 else if (!strcmp(optarg
, "idle"))
783 con
->dont_print
=FALSE
;
790 con
->dont_print
=FALSE
;
792 #ifdef HAVE_GETOPT_LONG
793 // Point arg to the argument in which this option was found.
794 arg
= argv
[optind
-1];
795 // Check whether the option is a long option that doesn't map to -h.
796 if (arg
[1] == '-' && optchar
!= 'h') {
797 // Iff optopt holds a valid option then argument must be missing.
798 if (optopt
&& (strchr(shortopts
, optopt
) != NULL
)) {
799 pout("=======> ARGUMENT REQUIRED FOR OPTION: %s\n", arg
+2);
800 printvalidarglistmessage(optopt
);
802 pout("=======> UNRECOGNIZED OPTION: %s\n",arg
+2);
804 pout("=======> %s", extraerror
);
810 // Iff optopt holds a valid option then argument must be
811 // missing. Note (BA) this logic seems to fail using Solaris
813 if (strchr(shortopts
, optopt
) != NULL
) {
814 pout("=======> ARGUMENT REQUIRED FOR OPTION: %c\n", optopt
);
815 printvalidarglistmessage(optopt
);
817 pout("=======> UNRECOGNIZED OPTION: %c\n",optopt
);
819 pout("=======> %s", extraerror
);
825 } // closes switch statement to process command-line options
827 // Check to see if option had an unrecognized or incorrect argument.
830 // It would be nice to print the actual option name given by the user
831 // here, but we just print the short form. Please fix this if you know
832 // a clean way to do it.
833 pout("=======> INVALID ARGUMENT TO -%c: %s\n", optchar
, optarg
);
834 printvalidarglistmessage(optchar
);
836 pout("=======> %s", extraerror
);
841 // At this point we have processed all command-line options. If the
842 // print output is switchable, then start with the print output
844 if (con
->printing_switchable
)
845 con
->dont_print
=TRUE
;
847 // error message if user has asked for more than one test
848 if (1<(con
->smartexeoffimmediate
+con
->smartshortselftest
+con
->smartextendselftest
+
849 con
->smartshortcapselftest
+con
->smartextendcapselftest
+con
->smartselftestabort
+ (con
->smartselectivenumspans
>0?1:0))){
850 con
->dont_print
=FALSE
;
852 pout("\nERROR: smartctl can only run a single test type (or abort) at a time.\n");
857 // error message if user has set selective self-test options without
858 // asking for a selective self-test
859 if ((con
->pendingtime
|| con
->scanafterselect
) && !con
->smartselectivenumspans
){
860 con
->dont_print
=FALSE
;
862 if (con
->pendingtime
)
863 pout("\nERROR: smartctl -t pending,N must be used with -t select,N-M.\n");
865 pout("\nERROR: smartctl -t afterselect,(on|off) must be used with -t select,N-M.\n");
870 // If captive option was used, change test type if appropriate.
871 if (captive
&& con
->smartshortselftest
) {
872 con
->smartshortselftest
= FALSE
;
873 con
->smartshortcapselftest
= TRUE
;
874 con
->testcase
= SHORT_CAPTIVE_SELF_TEST
;
875 } else if (captive
&& con
->smartextendselftest
) {
876 con
->smartextendselftest
= FALSE
;
877 con
->smartextendcapselftest
= TRUE
;
878 con
->testcase
= EXTEND_CAPTIVE_SELF_TEST
;
880 else if (captive
&& con
->smartconveyanceselftest
) {
881 con
->smartconveyanceselftest
= FALSE
;
882 con
->smartconveyancecapselftest
= TRUE
;
883 con
->testcase
= CONVEYANCE_CAPTIVE_SELF_TEST
;
885 else if (captive
&& con
->smartselectiveselftest
) {
886 con
->smartselectiveselftest
= FALSE
;
887 con
->smartselectivecapselftest
= TRUE
;
888 con
->testcase
= SELECTIVE_CAPTIVE_SELF_TEST
;
891 // From here on, normal operations...
894 // Warn if the user has provided no device name
896 pout("ERROR: smartctl requires a device name as the final command-line argument.\n\n");
901 // Warn if the user has provided more than one device name
904 pout("ERROR: smartctl takes ONE device name as the final command-line argument.\n");
905 pout("You have provided %d device names:\n",argc
-optind
);
906 for (i
=0; i
<argc
-optind
; i
++)
907 pout("%s\n",argv
[optind
+i
]);
913 // Printing function (controlled by global con->dont_print)
914 // [From GLIBC Manual: Since the prototype doesn't specify types for
915 // optional arguments, in a call to a variadic function the default
916 // argument promotions are performed on the optional argument
917 // values. This means the objects of type char or short int (whether
918 // signed or not) are promoted to either int or unsigned int, as
920 void pout(const char *fmt
, ...){
923 // initialize variable argument list
925 if (con
->dont_print
){
937 // This function is used by utility.cpp to report LOG_CRIT errors.
938 // The smartctl version prints to stdout instead of syslog().
939 void PrintOut(int priority
, const char *fmt
, ...) {
942 // avoid warning message about unused variable from gcc -W: just
943 // change value of local copy.
954 int main (int argc
, char **argv
){
957 smartmonctrl control
;
960 // define control block for external functions
963 // Part input arguments
964 ParseOpts(argc
,argv
);
966 device
= argv
[argc
-1];
968 // Device name "-": Parse "smartctl -r ataioctl,2 ..." output
969 if (!strcmp(device
,"-")) {
970 if (con
->controller_type
!= CONTROLLER_UNKNOWN
) {
971 pout("Smartctl: -d option is not allowed in conjunction with device name \"-\".\n");
975 con
->controller_type
= CONTROLLER_PARSEDEV
;
978 // If use has specified 3ware controller, determine which interface
979 if (con
->controller_type
== CONTROLLER_3WARE
) {
980 con
->controller_type
=guess_device_type(device
);
981 if (con
->controller_type
!=CONTROLLER_3WARE_9000_CHAR
&& con
->controller_type
!=CONTROLLER_3WARE_678K_CHAR
)
982 con
->controller_type
= CONTROLLER_3WARE_678K
;
985 if (con
->controller_type
== CONTROLLER_UNKNOWN
)
986 con
->controller_type
=guess_device_type(device
);
988 if (con
->controller_type
== CONTROLLER_UNKNOWN
) {
989 pout("Smartctl: please specify device type with the -d option.\n");
994 // set up mode for open() call. SCSI case is:
995 switch (con
->controller_type
) {
996 case CONTROLLER_SCSI
:
1000 case CONTROLLER_3WARE_9000_CHAR
:
1001 mode
="ATA_3WARE_9000";
1003 case CONTROLLER_3WARE_678K_CHAR
:
1004 mode
="ATA_3WARE_678K";
1006 case CONTROLLER_CCISS
:
1014 // open device - SCSI devices are opened (O_RDWR | O_NONBLOCK) so the
1015 // scsi generic device can be used (needs write permission for MODE
1016 // SELECT command) plus O_NONBLOCK to stop open hanging if media not
1017 // present (e.g. with st). Opening is retried O_RDONLY if read-only
1018 // media prevents opening O_RDWR (it cannot happen for scsi generic
1019 // devices, but it can for the others).
1020 if (con
->controller_type
!= CONTROLLER_PARSEDEV
)
1021 fd
= deviceopen(device
, mode
);
1023 fd
= parsedev_open(device
);
1026 snprintf(errmsg
,256,"Smartctl open device: %s failed",argv
[argc
-1]);
1032 // now call appropriate ATA or SCSI routine
1033 switch (con
->controller_type
) {
1034 case CONTROLLER_UNKNOWN
:
1035 // we should never fall into this branch!
1036 pout("Smartctl: please specify device type with the -d option.\n");
1040 case CONTROLLER_SCSI
:
1041 retval
= scsiPrintMain(fd
);
1042 if ((0 == retval
) && (CONTROLLER_SAT
== con
->controller_type
))
1043 retval
= ataPrintMain(fd
);
1045 case CONTROLLER_CCISS
:
1046 // route the cciss command through scsiPrintMain.
1047 // cciss pass-throughs will separeate from the SCSI data-path.
1048 retval
= scsiPrintMain(fd
);
1051 retval
= ataPrintMain(fd
);
1055 if (con
->controller_type
!= CONTROLLER_PARSEDEV
)