version 1.1, 2012/02/21 16:32:16
|
version 1.1.1.3, 2013/07/22 01:17:36
|
Line 4
|
Line 4
|
* Home page of code is: http://smartmontools.sourceforge.net |
* Home page of code is: http://smartmontools.sourceforge.net |
* |
* |
* Copyright (C) 2002-11 Bruce Allen <smartmontools-support@lists.sourceforge.net> |
* Copyright (C) 2002-11 Bruce Allen <smartmontools-support@lists.sourceforge.net> |
* Copyright (C) 2008-11 Christian Franke <smartmontools-support@lists.sourceforge.net> | * Copyright (C) 2008-12 Christian Franke <smartmontools-support@lists.sourceforge.net> |
* Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> |
* Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> |
* |
* |
* This program is free software; you can redistribute it and/or modify |
* This program is free software; you can redistribute it and/or modify |
Line 13
|
Line 13
|
* any later version. |
* any later version. |
* |
* |
* You should have received a copy of the GNU General Public License |
* You should have received a copy of the GNU General Public License |
* (for example COPYING); if not, write to the Free | * (for example COPYING); If not, see <http://www.gnu.org/licenses/>. |
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. | |
* |
* |
* This code was originally developed as a Senior Thesis by Michael Cornwell |
* This code was originally developed as a Senior Thesis by Michael Cornwell |
* at the Concurrent Systems Laboratory (now part of the Storage Systems |
* at the Concurrent Systems Laboratory (now part of the Storage Systems |
Line 41
|
Line 40
|
#include <sys/param.h> |
#include <sys/param.h> |
#endif |
#endif |
|
|
#if defined(__QNXNTO__) |
|
#include <new> // TODO: Why is this include necessary on QNX ? |
|
#endif |
|
|
|
#include "int64.h" |
#include "int64.h" |
#include "atacmds.h" |
#include "atacmds.h" |
#include "dev_interface.h" |
#include "dev_interface.h" |
Line 73 static void UsageSummary()
|
Line 68 static void UsageSummary()
|
return; |
return; |
} |
} |
|
|
static std::string getvalidarglist(char opt); | static std::string getvalidarglist(int opt); |
|
|
/* void prints help information for command syntax */ |
/* void prints help information for command syntax */ |
static void Usage() |
static void Usage() |
Line 85 static void Usage()
|
Line 80 static void Usage()
|
" Display this help and exit\n\n" |
" Display this help and exit\n\n" |
" -V, --version, --copyright, --license\n" |
" -V, --version, --copyright, --license\n" |
" Print license, copyright, and version information and exit\n\n" |
" Print license, copyright, and version information and exit\n\n" |
" -i, --info \n" | " -i, --info\n" |
" Show identity information for device\n\n" |
" Show identity information for device\n\n" |
" -a, --all \n" | " --identify[=[w][nvb]]\n" |
| " Show words and bits from IDENTIFY DEVICE data (ATA)\n\n" |
| " -g NAME, --get=NAME\n" |
| " Get device setting: all, aam, apm, lookahead, security, wcache, rcache\n\n" |
| " -a, --all\n" |
" Show all SMART information for device\n\n" |
" Show all SMART information for device\n\n" |
" -x, --xall\n" |
" -x, --xall\n" |
" Show all information for device\n\n" |
" Show all information for device\n\n" |
Line 119 static void Usage()
|
Line 118 static void Usage()
|
" Enable/disable automatic offline testing on device (on/off)\n\n" |
" Enable/disable automatic offline testing on device (on/off)\n\n" |
" -S VALUE, --saveauto=VALUE (ATA)\n" |
" -S VALUE, --saveauto=VALUE (ATA)\n" |
" Enable/disable Attribute autosave on device (on/off)\n\n" |
" Enable/disable Attribute autosave on device (on/off)\n\n" |
|
" -s NAME[,VALUE], --set=NAME[,VALUE]\n" |
|
" Enable/disable/change device setting: aam,[N|off], apm,[N|off],\n" |
|
" lookahead,[on|off], security-freeze, standby,[N|off|now],\n" |
|
" wcache,[on|off], rcache,[on|off]\n\n" |
); |
); |
printf( |
printf( |
"======================================= READ AND DISPLAY DATA OPTIONS =====\n\n" |
"======================================= READ AND DISPLAY DATA OPTIONS =====\n\n" |
Line 129 static void Usage()
|
Line 132 static void Usage()
|
" -A, --attributes\n" |
" -A, --attributes\n" |
" Show device SMART vendor-specific Attributes and values\n\n" |
" Show device SMART vendor-specific Attributes and values\n\n" |
" -f FORMAT, --format=FORMAT (ATA)\n" |
" -f FORMAT, --format=FORMAT (ATA)\n" |
" Set output format for attributes to one of: old, brief\n\n" | " Set output format for attributes: old, brief, hex[,id|val]\n\n" |
" -l TYPE, --log=TYPE\n" |
" -l TYPE, --log=TYPE\n" |
" Show device log. TYPE: error, selftest, selective, directory[,g|s],\n" |
" Show device log. TYPE: error, selftest, selective, directory[,g|s],\n" |
" xerror[,N][,error], xselftest[,N][,selftest],\n" |
" xerror[,N][,error], xselftest[,N][,selftest],\n" |
Line 140 static void Usage()
|
Line 143 static void Usage()
|
" -v N,OPTION , --vendorattribute=N,OPTION (ATA)\n" |
" -v N,OPTION , --vendorattribute=N,OPTION (ATA)\n" |
" Set display OPTION for vendor Attribute N (see man page)\n\n" |
" Set display OPTION for vendor Attribute N (see man page)\n\n" |
" -F TYPE, --firmwarebug=TYPE (ATA)\n" |
" -F TYPE, --firmwarebug=TYPE (ATA)\n" |
" Use firmware bug workaround: none, samsung, samsung2,\n" | " Use firmware bug workaround:\n" |
" samsung3, swapid\n\n" | " %s, swapid\n\n" |
" -P TYPE, --presets=TYPE (ATA)\n" |
" -P TYPE, --presets=TYPE (ATA)\n" |
" Drive-specific presets: use, ignore, show, showall\n\n" |
" Drive-specific presets: use, ignore, show, showall\n\n" |
" -B [+]FILE, --drivedb=[+]FILE (ATA)\n" |
" -B [+]FILE, --drivedb=[+]FILE (ATA)\n" |
" Read and replace [add] drive database from FILE\n" |
" Read and replace [add] drive database from FILE\n" |
" [default is +%s", |
" [default is +%s", |
|
get_valid_firmwarebug_args(), |
get_drivedb_path_add() |
get_drivedb_path_add() |
); |
); |
#ifdef SMARTMONTOOLS_DRIVEDBDIR |
#ifdef SMARTMONTOOLS_DRIVEDBDIR |
Line 160 static void Usage()
|
Line 164 static void Usage()
|
"]\n\n" |
"]\n\n" |
"============================================ DEVICE SELF-TEST OPTIONS =====\n\n" |
"============================================ DEVICE SELF-TEST OPTIONS =====\n\n" |
" -t TEST, --test=TEST\n" |
" -t TEST, --test=TEST\n" |
" Run test. TEST: offline, short, long, conveyance, vendor,N,\n" | " Run test. TEST: offline, short, long, conveyance, force, vendor,N,\n" |
" select,M-N, pending,N, afterselect,[on|off]\n\n" |
" select,M-N, pending,N, afterselect,[on|off]\n\n" |
" -C, --captive\n" |
" -C, --captive\n" |
" Do test in captive mode (along with -t)\n\n" |
" Do test in captive mode (along with -t)\n\n" |
Line 172 static void Usage()
|
Line 176 static void Usage()
|
printf("%s\n", examples.c_str()); |
printf("%s\n", examples.c_str()); |
} |
} |
|
|
|
// Values for --long only options, see parse_options() |
|
enum { opt_identify = 1000, opt_scan, opt_scan_open, opt_set, opt_smart }; |
|
|
/* Returns a string containing a formatted list of the valid arguments |
/* Returns a string containing a formatted list of the valid arguments |
to the option opt or empty on failure. Note 'v' case different */ |
to the option opt or empty on failure. Note 'v' case different */ |
static std::string getvalidarglist(char opt) | static std::string getvalidarglist(int opt) |
{ |
{ |
switch (opt) { |
switch (opt) { |
case 'q': |
case 'q': |
Line 187 static std::string getvalidarglist(char opt)
|
Line 194 static std::string getvalidarglist(char opt)
|
return "warn, exit, ignore"; |
return "warn, exit, ignore"; |
case 'r': |
case 'r': |
return "ioctl[,N], ataioctl[,N], scsiioctl[,N]"; |
return "ioctl[,N], ataioctl[,N], scsiioctl[,N]"; |
case 's': | case opt_smart: |
case 'o': |
case 'o': |
case 'S': |
case 'S': |
return "on, off"; |
return "on, off"; |
Line 202 static std::string getvalidarglist(char opt)
|
Line 209 static std::string getvalidarglist(char opt)
|
case 'P': |
case 'P': |
return "use, ignore, show, showall"; |
return "use, ignore, show, showall"; |
case 't': |
case 't': |
return "offline, short, long, conveyance, vendor,N, select,M-N, " | return "offline, short, long, conveyance, force, vendor,N, select,M-N, " |
"pending,N, afterselect,[on|off]"; |
"pending,N, afterselect,[on|off]"; |
case 'F': |
case 'F': |
return "none, samsung, samsung2, samsung3, swapid"; | return std::string(get_valid_firmwarebug_args()) + ", swapid"; |
case 'n': |
case 'n': |
return "never, sleep, standby, idle"; |
return "never, sleep, standby, idle"; |
case 'f': |
case 'f': |
return "old, brief"; | return "old, brief, hex[,id|val]"; |
| case 'g': |
| return "aam, apm, lookahead, security, wcache, rcache"; |
| case opt_set: |
| return "aam,[N|off], apm,[N|off], lookahead,[on|off], security-freeze, " |
| "standby,[N|off|now], wcache,[on|off], rcache,[on|off]"; |
| case 's': |
| return getvalidarglist(opt_smart)+", "+getvalidarglist(opt_set); |
| case opt_identify: |
| return "n, wn, w, v, wv, wb"; |
case 'v': |
case 'v': |
default: |
default: |
return ""; |
return ""; |
Line 218 static std::string getvalidarglist(char opt)
|
Line 234 static std::string getvalidarglist(char opt)
|
|
|
/* Prints the message "=======> VALID ARGUMENTS ARE: <LIST> \n", where |
/* Prints the message "=======> VALID ARGUMENTS ARE: <LIST> \n", where |
<LIST> is the list of valid arguments for option opt. */ |
<LIST> is the list of valid arguments for option opt. */ |
static void printvalidarglistmessage(char opt) | static void printvalidarglistmessage(int opt) |
{ |
{ |
if (opt=='v'){ |
if (opt=='v'){ |
pout("=======> VALID ARGUMENTS ARE:\n\thelp\n%s\n<=======\n", |
pout("=======> VALID ARGUMENTS ARE:\n\thelp\n%s\n<=======\n", |
Line 244 static checksum_err_mode_t checksum_err_mode = CHECKSU
|
Line 260 static checksum_err_mode_t checksum_err_mode = CHECKSU
|
|
|
static void scan_devices(const char * type, bool with_open, char ** argv); |
static void scan_devices(const char * type, bool with_open, char ** argv); |
|
|
|
|
/* Takes command options and sets features to be run */ |
/* Takes command options and sets features to be run */ |
static const char * parse_options(int argc, char** argv, |
static const char * parse_options(int argc, char** argv, |
ata_print_options & ataopts, | ata_print_options & ataopts, scsi_print_options & scsiopts, |
scsi_print_options & scsiopts) | bool & print_type_only) |
{ |
{ |
// Please update getvalidarglist() if you edit shortopts |
// Please update getvalidarglist() if you edit shortopts |
const char *shortopts = "h?Vq:d:T:b:r:s:o:S:HcAl:iaxv:P:t:CXF:n:B:f:"; | const char *shortopts = "h?Vq:d:T:b:r:s:o:S:HcAl:iaxv:P:t:CXF:n:B:f:g:"; |
// Please update getvalidarglist() if you edit longopts |
// Please update getvalidarglist() if you edit longopts |
enum { opt_scan = 1000, opt_scan_open = 1001 }; |
|
struct option longopts[] = { |
struct option longopts[] = { |
{ "help", no_argument, 0, 'h' }, |
{ "help", no_argument, 0, 'h' }, |
{ "usage", no_argument, 0, 'h' }, |
{ "usage", no_argument, 0, 'h' }, |
Line 264 static const char * parse_options(int argc, char** arg
|
Line 280 static const char * parse_options(int argc, char** arg
|
{ "tolerance", required_argument, 0, 'T' }, |
{ "tolerance", required_argument, 0, 'T' }, |
{ "badsum", required_argument, 0, 'b' }, |
{ "badsum", required_argument, 0, 'b' }, |
{ "report", required_argument, 0, 'r' }, |
{ "report", required_argument, 0, 'r' }, |
{ "smart", required_argument, 0, 's' }, | { "smart", required_argument, 0, opt_smart }, |
{ "offlineauto", required_argument, 0, 'o' }, |
{ "offlineauto", required_argument, 0, 'o' }, |
{ "saveauto", required_argument, 0, 'S' }, |
{ "saveauto", required_argument, 0, 'S' }, |
{ "health", no_argument, 0, 'H' }, |
{ "health", no_argument, 0, 'H' }, |
Line 283 static const char * parse_options(int argc, char** arg
|
Line 299 static const char * parse_options(int argc, char** arg
|
{ "nocheck", required_argument, 0, 'n' }, |
{ "nocheck", required_argument, 0, 'n' }, |
{ "drivedb", required_argument, 0, 'B' }, |
{ "drivedb", required_argument, 0, 'B' }, |
{ "format", required_argument, 0, 'f' }, |
{ "format", required_argument, 0, 'f' }, |
|
{ "get", required_argument, 0, 'g' }, |
|
{ "identify", optional_argument, 0, opt_identify }, |
|
{ "set", required_argument, 0, opt_set }, |
{ "scan", no_argument, 0, opt_scan }, |
{ "scan", no_argument, 0, opt_scan }, |
{ "scan-open", no_argument, 0, opt_scan_open }, |
{ "scan-open", no_argument, 0, opt_scan_open }, |
{ 0, 0, 0, 0 } |
{ 0, 0, 0, 0 } |
Line 323 static const char * parse_options(int argc, char** arg
|
Line 342 static const char * parse_options(int argc, char** arg
|
} |
} |
break; |
break; |
case 'd': |
case 'd': |
type = (strcmp(optarg, "auto") ? optarg : (char *)0); | if (!strcmp(optarg, "test")) |
| print_type_only = true; |
| else |
| type = (strcmp(optarg, "auto") ? optarg : (char *)0); |
break; |
break; |
case 'T': |
case 'T': |
if (!strcmp(optarg,"normal")) { |
if (!strcmp(optarg,"normal")) { |
Line 375 static const char * parse_options(int argc, char** arg
|
Line 397 static const char * parse_options(int argc, char** arg
|
free(s); |
free(s); |
} |
} |
break; |
break; |
|
|
case 's': |
case 's': |
|
case opt_smart: // --smart |
if (!strcmp(optarg,"on")) { |
if (!strcmp(optarg,"on")) { |
ataopts.smart_enable = scsiopts.smart_enable = true; |
ataopts.smart_enable = scsiopts.smart_enable = true; |
ataopts.smart_disable = scsiopts.smart_disable = false; |
ataopts.smart_disable = scsiopts.smart_disable = false; |
} else if (!strcmp(optarg,"off")) { |
} else if (!strcmp(optarg,"off")) { |
ataopts.smart_disable = scsiopts.smart_disable = true; |
ataopts.smart_disable = scsiopts.smart_disable = true; |
ataopts.smart_enable = scsiopts.smart_enable = false; |
ataopts.smart_enable = scsiopts.smart_enable = false; |
|
} else if (optchar == 's') { |
|
goto case_s_continued; // --set, see below |
} else { |
} else { |
badarg = true; |
badarg = true; |
} |
} |
break; |
break; |
|
|
case 'o': |
case 'o': |
if (!strcmp(optarg,"on")) { |
if (!strcmp(optarg,"on")) { |
ataopts.smart_auto_offl_enable = true; |
ataopts.smart_auto_offl_enable = true; |
Line 413 static const char * parse_options(int argc, char** arg
|
Line 440 static const char * parse_options(int argc, char** arg
|
scsiopts.smart_ss_media_log = true; |
scsiopts.smart_ss_media_log = true; |
break; |
break; |
case 'F': |
case 'F': |
if (!strcmp(optarg,"none")) { | if (!strcmp(optarg, "swapid")) |
ataopts.fix_firmwarebug = FIX_NONE; | |
} else if (!strcmp(optarg,"samsung")) { | |
ataopts.fix_firmwarebug = FIX_SAMSUNG; | |
} else if (!strcmp(optarg,"samsung2")) { | |
ataopts.fix_firmwarebug = FIX_SAMSUNG2; | |
} else if (!strcmp(optarg,"samsung3")) { | |
ataopts.fix_firmwarebug = FIX_SAMSUNG3; | |
} else if (!strcmp(optarg,"swapid")) { | |
ataopts.fix_swapped_id = true; |
ataopts.fix_swapped_id = true; |
} else { | else if (!parse_firmwarebug_def(optarg, ataopts.firmwarebugs)) |
badarg = true; |
badarg = true; |
} |
|
break; |
break; |
case 'c': |
case 'c': |
ataopts.smart_general_values = true; |
ataopts.smart_general_values = true; |
Line 472 static const char * parse_options(int argc, char** arg
|
Line 490 static const char * parse_options(int argc, char** arg
|
unsigned interval = 0; int n1 = -1, n2 = -1, len = strlen(optarg); |
unsigned interval = 0; int n1 = -1, n2 = -1, len = strlen(optarg); |
if (!( sscanf(optarg,"scttempint,%u%n,p%n", &interval, &n1, &n2) == 1 |
if (!( sscanf(optarg,"scttempint,%u%n,p%n", &interval, &n1, &n2) == 1 |
&& 0 < interval && interval <= 0xffff && (n1 == len || n2 == len))) { |
&& 0 < interval && interval <= 0xffff && (n1 == len || n2 == len))) { |
strcpy(extraerror, "Option -l scttempint,N[,p] must have positive integer N\n"); | snprintf(extraerror, sizeof(extraerror), "Option -l scttempint,N[,p] must have positive integer N\n"); |
badarg = true; |
badarg = true; |
} |
} |
ataopts.sct_temp_int = interval; |
ataopts.sct_temp_int = interval; |
Line 528 static const char * parse_options(int argc, char** arg
|
Line 546 static const char * parse_options(int argc, char** arg
|
ataopts.sct_erc_writetime = wt; |
ataopts.sct_erc_writetime = wt; |
} |
} |
else { |
else { |
sprintf(extraerror, "Option -l scterc,[READTIME,WRITETIME] syntax error\n"); | snprintf(extraerror, sizeof(extraerror), "Option -l scterc,[READTIME,WRITETIME] syntax error\n"); |
badarg = true; |
badarg = true; |
} |
} |
} else if ( !strncmp(optarg, "gplog," , sizeof("gplog," )-1) |
} else if ( !strncmp(optarg, "gplog," , sizeof("gplog," )-1) |
Line 544 static const char * parse_options(int argc, char** arg
|
Line 562 static const char * parse_options(int argc, char** arg
|
const char * erropt = (gpl ? "gplog" : "smartlog"); |
const char * erropt = (gpl ? "gplog" : "smartlog"); |
if (!( n1 == len || n2 == len |
if (!( n1 == len || n2 == len |
|| (n3 == len && (sign == '+' || sign == '-')))) { |
|| (n3 == len && (sign == '+' || sign == '-')))) { |
sprintf(extraerror, "Option -l %s,ADDR[,FIRST[-LAST|+SIZE]] syntax error\n", erropt); | snprintf(extraerror, sizeof(extraerror), "Option -l %s,ADDR[,FIRST[-LAST|+SIZE]] syntax error\n", erropt); |
badarg = true; |
badarg = true; |
} |
} |
else if (!( logaddr <= 0xff && page <= (gpl ? 0xffffU : 0x00ffU) |
else if (!( logaddr <= 0xff && page <= (gpl ? 0xffffU : 0x00ffU) |
&& 0 < nsectors |
&& 0 < nsectors |
&& (nsectors <= (gpl ? 0xffffU : 0xffU) || nsectors == ~0U) |
&& (nsectors <= (gpl ? 0xffffU : 0xffU) || nsectors == ~0U) |
&& (sign != '-' || page <= nsectors) )) { |
&& (sign != '-' || page <= nsectors) )) { |
sprintf(extraerror, "Option -l %s,ADDR[,FIRST[-LAST|+SIZE]] parameter out of range\n", erropt); | snprintf(extraerror, sizeof(extraerror), "Option -l %s,ADDR[,FIRST[-LAST|+SIZE]] parameter out of range\n", erropt); |
badarg = true; |
badarg = true; |
} |
} |
else { |
else { |
Line 567 static const char * parse_options(int argc, char** arg
|
Line 585 static const char * parse_options(int argc, char** arg
|
case 'i': |
case 'i': |
ataopts.drive_info = scsiopts.drive_info = true; |
ataopts.drive_info = scsiopts.drive_info = true; |
break; |
break; |
|
|
|
case opt_identify: |
|
ataopts.identify_word_level = ataopts.identify_bit_level = 0; |
|
if (optarg) { |
|
for (int i = 0; optarg[i]; i++) { |
|
switch (optarg[i]) { |
|
case 'w': ataopts.identify_word_level = 1; break; |
|
case 'n': ataopts.identify_bit_level = -1; break; |
|
case 'v': ataopts.identify_bit_level = 1; break; |
|
case 'b': ataopts.identify_bit_level = 2; break; |
|
default: badarg = true; |
|
} |
|
} |
|
} |
|
break; |
|
|
case 'a': |
case 'a': |
ataopts.drive_info = scsiopts.drive_info = true; |
ataopts.drive_info = scsiopts.drive_info = true; |
ataopts.smart_check_status = scsiopts.smart_check_status = true; |
ataopts.smart_check_status = scsiopts.smart_check_status = true; |
Line 592 static const char * parse_options(int argc, char** arg
|
Line 626 static const char * parse_options(int argc, char** arg
|
ataopts.smart_logdir = ataopts.gp_logdir = true; |
ataopts.smart_logdir = ataopts.gp_logdir = true; |
ataopts.sct_temp_sts = ataopts.sct_temp_hist = true; |
ataopts.sct_temp_sts = ataopts.sct_temp_hist = true; |
ataopts.sct_erc_get = true; |
ataopts.sct_erc_get = true; |
|
ataopts.devstat_all_pages = true; |
ataopts.sataphy = true; |
ataopts.sataphy = true; |
|
ataopts.get_set_used = true; |
|
ataopts.get_aam = ataopts.get_apm = true; |
|
ataopts.get_security = true; |
|
ataopts.get_lookahead = ataopts.get_wcache = true; |
|
scsiopts.get_rcd = scsiopts.get_wce = true; |
scsiopts.smart_background_log = true; |
scsiopts.smart_background_log = true; |
scsiopts.smart_ss_media_log = true; |
scsiopts.smart_ss_media_log = true; |
scsiopts.sasphy = true; |
scsiopts.sasphy = true; |
if (!output_format_set) |
if (!output_format_set) |
ataopts.output_format = 1; // '-f brief' | ataopts.output_format |= ata_print_options::FMT_BRIEF; |
break; |
break; |
case 'v': |
case 'v': |
// parse vendor-specific definitions of attributes |
// parse vendor-specific definitions of attributes |
Line 648 static const char * parse_options(int argc, char** arg
|
Line 688 static const char * parse_options(int argc, char** arg
|
} else if (!strcmp(optarg,"conveyance")) { |
} else if (!strcmp(optarg,"conveyance")) { |
testcnt++; |
testcnt++; |
ataopts.smart_selftest_type = CONVEYANCE_SELF_TEST; |
ataopts.smart_selftest_type = CONVEYANCE_SELF_TEST; |
|
} else if (!strcmp(optarg,"force")) { |
|
ataopts.smart_selftest_force = true; |
|
scsiopts.smart_selftest_force = true; |
} else if (!strcmp(optarg,"afterselect,on")) { |
} else if (!strcmp(optarg,"afterselect,on")) { |
// scan remainder of disk after doing selected segment |
// scan remainder of disk after doing selected segment |
ataopts.smart_selective_args.scan_after_select = 2; |
ataopts.smart_selective_args.scan_after_select = 2; |
Line 661 static const char * parse_options(int argc, char** arg
|
Line 704 static const char * parse_options(int argc, char** arg
|
errno=0; |
errno=0; |
i=(int)strtol(optarg+strlen("pending,"), &tailptr, 10); |
i=(int)strtol(optarg+strlen("pending,"), &tailptr, 10); |
if (errno || *tailptr != '\0') { |
if (errno || *tailptr != '\0') { |
sprintf(extraerror, "Option -t pending,N requires N to be a non-negative integer\n"); | snprintf(extraerror, sizeof(extraerror), "Option -t pending,N requires N to be a non-negative integer\n"); |
badarg = true; |
badarg = true; |
} else if (i<0 || i>65535) { |
} else if (i<0 || i>65535) { |
sprintf(extraerror, "Option -t pending,N (N=%d) must have 0 <= N <= 65535\n", i); | snprintf(extraerror, sizeof(extraerror), "Option -t pending,N (N=%d) must have 0 <= N <= 65535\n", i); |
badarg = true; |
badarg = true; |
} else { |
} else { |
ataopts.smart_selective_args.pending_time = i+1; |
ataopts.smart_selective_args.pending_time = i+1; |
Line 675 static const char * parse_options(int argc, char** arg
|
Line 718 static const char * parse_options(int argc, char** arg
|
// parse range of LBAs to test |
// parse range of LBAs to test |
uint64_t start, stop; int mode; |
uint64_t start, stop; int mode; |
if (split_selective_arg(optarg, &start, &stop, &mode)) { |
if (split_selective_arg(optarg, &start, &stop, &mode)) { |
sprintf(extraerror, "Option -t select,M-N must have non-negative integer M and N\n"); | snprintf(extraerror, sizeof(extraerror), "Option -t select,M-N must have non-negative integer M and N\n"); |
badarg = true; |
badarg = true; |
} else { |
} else { |
if (ataopts.smart_selective_args.num_spans >= 5 || start > stop) { |
if (ataopts.smart_selective_args.num_spans >= 5 || start > stop) { |
if (start > stop) { |
if (start > stop) { |
sprintf(extraerror, "ERROR: Start LBA (%"PRIu64") > ending LBA (%"PRId64") in argument \"%s\"\n", | snprintf(extraerror, sizeof(extraerror), "ERROR: Start LBA (%"PRIu64") > ending LBA (%"PRId64") in argument \"%s\"\n", |
start, stop, optarg); |
start, stop, optarg); |
} else { |
} else { |
sprintf(extraerror,"ERROR: No more than five selective self-test spans may be" | snprintf(extraerror, sizeof(extraerror),"ERROR: No more than five selective self-test spans may be" |
" defined\n"); |
" defined\n"); |
} |
} |
badarg = true; |
badarg = true; |
Line 695 static const char * parse_options(int argc, char** arg
|
Line 738 static const char * parse_options(int argc, char** arg
|
ataopts.smart_selftest_type = SELECTIVE_SELF_TEST; |
ataopts.smart_selftest_type = SELECTIVE_SELF_TEST; |
} |
} |
} else if (!strncmp(optarg, "scttempint", sizeof("scstempint")-1)) { |
} else if (!strncmp(optarg, "scttempint", sizeof("scstempint")-1)) { |
strcpy(extraerror, "-t scttempint is no longer supported, use -l scttempint instead\n"); | snprintf(extraerror, sizeof(extraerror), "-t scttempint is no longer supported, use -l scttempint instead\n"); |
badarg = true; |
badarg = true; |
} else if (!strncmp(optarg, "vendor,", sizeof("vendor,")-1)) { |
} else if (!strncmp(optarg, "vendor,", sizeof("vendor,")-1)) { |
unsigned subcmd = ~0U; int n = -1; |
unsigned subcmd = ~0U; int n = -1; |
if (!( sscanf(optarg, "%*[a-z],0x%x%n", &subcmd, &n) == 1 |
if (!( sscanf(optarg, "%*[a-z],0x%x%n", &subcmd, &n) == 1 |
&& subcmd <= 0xff && n == (int)strlen(optarg))) { |
&& subcmd <= 0xff && n == (int)strlen(optarg))) { |
strcpy(extraerror, "Option -t vendor,0xNN syntax error\n"); | snprintf(extraerror, sizeof(extraerror), "Option -t vendor,0xNN syntax error\n"); |
badarg = true; |
badarg = true; |
} |
} |
else |
else |
Line 732 static const char * parse_options(int argc, char** arg
|
Line 775 static const char * parse_options(int argc, char** arg
|
badarg = true; |
badarg = true; |
break; |
break; |
case 'f': |
case 'f': |
output_format_set = true; | if (!strcmp(optarg, "old")) { |
if (!strcmp(optarg,"old")) { | ataopts.output_format &= ~ata_print_options::FMT_BRIEF; |
ataopts.output_format = 0; | output_format_set = true; |
} else if (!strcmp(optarg,"brief")) { | |
ataopts.output_format = 1; | |
} else { | |
badarg = true; | |
} |
} |
|
else if (!strcmp(optarg, "brief")) { |
|
ataopts.output_format |= ata_print_options::FMT_BRIEF; |
|
output_format_set = true; |
|
} |
|
else if (!strcmp(optarg, "hex")) |
|
ataopts.output_format |= ata_print_options::FMT_HEX_ID |
|
| ata_print_options::FMT_HEX_VAL; |
|
else if (!strcmp(optarg, "hex,id")) |
|
ataopts.output_format |= ata_print_options::FMT_HEX_ID; |
|
else if (!strcmp(optarg, "hex,val")) |
|
ataopts.output_format |= ata_print_options::FMT_HEX_VAL; |
|
else |
|
badarg = true; |
break; |
break; |
case 'B': |
case 'B': |
{ |
{ |
Line 759 static const char * parse_options(int argc, char** arg
|
Line 811 static const char * parse_options(int argc, char** arg
|
EXIT(0); |
EXIT(0); |
break; |
break; |
|
|
|
case 'g': |
|
case_s_continued: // -s, see above |
|
case opt_set: // --set |
|
{ |
|
ataopts.get_set_used = true; |
|
bool get = (optchar == 'g'); |
|
char name[16+1]; unsigned val; |
|
int n1 = -1, n2 = -1, n3 = -1, len = strlen(optarg); |
|
if (sscanf(optarg, "%16[^,=]%n%*[,=]%n%u%n", name, &n1, &n2, &val, &n3) >= 1 |
|
&& (n1 == len || (!get && n2 > 0))) { |
|
bool on = (n2 > 0 && !strcmp(optarg+n2, "on")); |
|
bool off = (n2 > 0 && !strcmp(optarg+n2, "off")); |
|
if (n3 != len) |
|
val = ~0U; |
|
|
|
if (get && !strcmp(name, "all")) { |
|
ataopts.get_aam = ataopts.get_apm = true; |
|
ataopts.get_security = true; |
|
ataopts.get_lookahead = ataopts.get_wcache = true; |
|
scsiopts.get_rcd = scsiopts.get_wce = true; |
|
} |
|
else if (!strcmp(name, "aam")) { |
|
if (get) |
|
ataopts.get_aam = true; |
|
else if (off) |
|
ataopts.set_aam = -1; |
|
else if (val <= 254) |
|
ataopts.set_aam = val + 1; |
|
else { |
|
snprintf(extraerror, sizeof(extraerror), "Option -s aam,N must have 0 <= N <= 254\n"); |
|
badarg = true; |
|
} |
|
} |
|
else if (!strcmp(name, "apm")) { |
|
if (get) |
|
ataopts.get_apm = true; |
|
else if (off) |
|
ataopts.set_apm = -1; |
|
else if (1 <= val && val <= 254) |
|
ataopts.set_apm = val + 1; |
|
else { |
|
snprintf(extraerror, sizeof(extraerror), "Option -s apm,N must have 1 <= N <= 254\n"); |
|
badarg = true; |
|
} |
|
} |
|
else if (!strcmp(name, "lookahead")) { |
|
if (get) { |
|
ataopts.get_lookahead = true; |
|
} |
|
else if (off) |
|
ataopts.set_lookahead = -1; |
|
else if (on) |
|
ataopts.set_lookahead = 1; |
|
else |
|
badarg = true; |
|
} |
|
else if (!strcmp(name, "rcache")) { |
|
if (get) |
|
scsiopts.get_rcd = true; |
|
else if (off) |
|
scsiopts.set_rcd = -1; |
|
else if (on) |
|
scsiopts.set_rcd = 1; |
|
else |
|
badarg = true; |
|
} |
|
else if (get && !strcmp(name, "security")) { |
|
ataopts.get_security = true; |
|
} |
|
else if (!get && !strcmp(optarg, "security-freeze")) { |
|
ataopts.set_security_freeze = true; |
|
} |
|
else if (!get && !strcmp(optarg, "standby,now")) { |
|
ataopts.set_standby_now = true; |
|
} |
|
else if (!get && !strcmp(name, "standby")) { |
|
if (off) |
|
ataopts.set_standby = 0 + 1; |
|
else if (val <= 255) |
|
ataopts.set_standby = val + 1; |
|
else { |
|
snprintf(extraerror, sizeof(extraerror), "Option -s standby,N must have 0 <= N <= 255\n"); |
|
badarg = true; |
|
} |
|
} |
|
else if (!strcmp(name, "wcache")) { |
|
if (get) { |
|
ataopts.get_wcache = true; |
|
scsiopts.get_wce = true; |
|
} |
|
else if (off) { |
|
ataopts.set_wcache = -1; |
|
scsiopts.set_wce = -1; |
|
} |
|
else if (on) { |
|
ataopts.set_wcache = 1; |
|
scsiopts.set_wce = 1; |
|
} |
|
else |
|
badarg = true; |
|
} |
|
else |
|
badarg = true; |
|
} |
|
else |
|
badarg = true; |
|
} |
|
break; |
|
|
case opt_scan: |
case opt_scan: |
case opt_scan_open: |
case opt_scan_open: |
scan = optchar; |
scan = optchar; |
Line 773 static const char * parse_options(int argc, char** arg
|
Line 934 static const char * parse_options(int argc, char** arg
|
// Check whether the option is a long option that doesn't map to -h. |
// Check whether the option is a long option that doesn't map to -h. |
if (arg[1] == '-' && optchar != 'h') { |
if (arg[1] == '-' && optchar != 'h') { |
// Iff optopt holds a valid option then argument must be missing. |
// Iff optopt holds a valid option then argument must be missing. |
if (optopt && (strchr(shortopts, optopt) != NULL)) { | if (optopt && (optopt >= opt_scan || strchr(shortopts, optopt))) { |
pout("=======> ARGUMENT REQUIRED FOR OPTION: %s\n", arg+2); |
pout("=======> ARGUMENT REQUIRED FOR OPTION: %s\n", arg+2); |
printvalidarglistmessage(optopt); |
printvalidarglistmessage(optopt); |
} else |
} else |
Line 783 static const char * parse_options(int argc, char** arg
|
Line 944 static const char * parse_options(int argc, char** arg
|
UsageSummary(); |
UsageSummary(); |
EXIT(FAILCMD); |
EXIT(FAILCMD); |
} |
} |
if (optopt) { | if (0 < optopt && optopt < '~') { |
// Iff optopt holds a valid option then argument must be |
// Iff optopt holds a valid option then argument must be |
// missing. Note (BA) this logic seems to fail using Solaris |
// missing. Note (BA) this logic seems to fail using Solaris |
// getopt! |
// getopt! |
Line 807 static const char * parse_options(int argc, char** arg
|
Line 968 static const char * parse_options(int argc, char** arg
|
// It would be nice to print the actual option name given by the user |
// It would be nice to print the actual option name given by the user |
// here, but we just print the short form. Please fix this if you know |
// here, but we just print the short form. Please fix this if you know |
// a clean way to do it. |
// a clean way to do it. |
pout("=======> INVALID ARGUMENT TO -%c: %s\n", optchar, optarg); | char optstr[] = { (char)optchar, 0 }; |
| pout("=======> INVALID ARGUMENT TO -%s: %s\n", |
| (optchar == opt_identify ? "-identify" : |
| optchar == opt_set ? "-set" : |
| optchar == opt_smart ? "-smart" : optstr), optarg); |
printvalidarglistmessage(optchar); |
printvalidarglistmessage(optchar); |
if (extraerror[0]) |
if (extraerror[0]) |
pout("=======> %s", extraerror); |
pout("=======> %s", extraerror); |
Line 1046 static int main_worker(int argc, char **argv)
|
Line 1211 static int main_worker(int argc, char **argv)
|
// Parse input arguments |
// Parse input arguments |
ata_print_options ataopts; |
ata_print_options ataopts; |
scsi_print_options scsiopts; |
scsi_print_options scsiopts; |
const char * type = parse_options(argc, argv, ataopts, scsiopts); | bool print_type_only = false; |
| const char * type = parse_options(argc, argv, ataopts, scsiopts, print_type_only); |
|
|
// '-d test' -> Report result of autodetection |
|
bool print_type_only = (type && !strcmp(type, "test")); |
|
if (print_type_only) |
|
type = 0; |
|
|
|
const char * name = argv[argc-1]; |
const char * name = argv[argc-1]; |
|
|
smart_device_auto_ptr dev; |
smart_device_auto_ptr dev; |
if (!strcmp(name,"-")) { |
if (!strcmp(name,"-")) { |
// Parse "smartctl -r ataioctl,2 ..." output from stdin |
// Parse "smartctl -r ataioctl,2 ..." output from stdin |
if (type || print_type_only) { |
if (type || print_type_only) { |
pout("Smartctl: -d option is not allowed in conjunction with device name \"-\".\n"); | pout("-d option is not allowed in conjunction with device name \"-\".\n"); |
UsageSummary(); |
UsageSummary(); |
return FAILCMD; |
return FAILCMD; |
} |
} |
Line 1074 static int main_worker(int argc, char **argv)
|
Line 1235 static int main_worker(int argc, char **argv)
|
if (type) |
if (type) |
printvalidarglistmessage('d'); |
printvalidarglistmessage('d'); |
else |
else |
pout("Smartctl: please specify device type with the -d option.\n"); | pout("Please specify device type with the -d option.\n"); |
UsageSummary(); |
UsageSummary(); |
return FAILCMD; |
return FAILCMD; |
} |
} |