diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG index d2b97e1b4b63eb070e882435b5f155658a7ff47d..72131f76814555e120120d56c7e6a6d205e5422f 100644 --- a/sm5/CHANGELOG +++ b/sm5/CHANGELOG @@ -1,6 +1,6 @@ CHANGELOG for smartmontools -$Id: CHANGELOG,v 1.805 2009/06/18 17:24:51 chrfranke Exp $ +$Id: CHANGELOG,v 1.806 2009/06/20 17:58:33 chrfranke Exp $ The most recent version of this file is: http://smartmontools.cvs.sourceforge.net/smartmontools/sm5/CHANGELOG?view=markup @@ -41,6 +41,11 @@ NOTES FOR FUTURE RELEASES: see TODO file. <DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE> + [CF] Add 'options' parameter to SCSI printing routine. Move global + 'con->...' smartctl variables to 'options' parameters of + printing routines. + + variables used for drive presets by local variables. [CF] Windows: Remove outdated entry about undocumented system calls from WARNINGS file. diff --git a/sm5/ataprint.cpp b/sm5/ataprint.cpp index 78faf9d9abb805fe20177bc53349d3ddf980f335..d2e0a0e9a46c5ba3e66af98fdeb3461c6db91a54 100644 --- a/sm5/ataprint.cpp +++ b/sm5/ataprint.cpp @@ -44,7 +44,7 @@ #include "utility.h" #include "knowndrives.h" -const char *ataprint_c_cvsid="$Id: ataprint.cpp,v 1.211 2009/06/13 14:56:20 chrfranke Exp $" +const char *ataprint_c_cvsid="$Id: ataprint.cpp,v 1.212 2009/06/20 17:58:33 chrfranke Exp $" ATACMDNAMES_H_CVSID ATACMDS_H_CVSID ATAPRINT_H_CVSID CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID KNOWNDRIVES_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID; // for passing global control variables @@ -1713,7 +1713,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) const char * powername = 0; char powerchg = 0; // If requested, check power mode first - if (con->powermode) { + if (options.powermode) { unsigned char powerlimit = 0xff; int powermode = ataCheckPowerMode(device); switch (powermode) { @@ -1734,7 +1734,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) break; } if (powername) { - if (con->powermode >= powerlimit) { + if (options.powermode >= powerlimit) { pout("Device is in %s mode, exit(%d)\n", powername, FAILPOWER); return FAILPOWER; } @@ -1763,7 +1763,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) // Print most drive identity information if requested bool known = false; - if (con->driveinfo){ + if (options.drive_info) { pout("=== START OF INFORMATION SECTION ===\n"); known = PrintDriveInfo(&drive, options.fix_swapped_id); } @@ -1797,11 +1797,12 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) pout(" SMART ENABLE appeared to work! Continuing.\n"); supported=1; } - if (!con->driveinfo) pout("\n"); + if (!options.drive_info) + pout("\n"); } // Now print remaining drive info: is SMART enabled? - if (con->driveinfo){ + if (options.drive_info) { int ison=ataIsSmartEnabled(&drive),isenabled=ison; if (ison==-1) { @@ -1835,13 +1836,13 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) } // START OF THE ENABLE/DISABLE SECTION OF THE CODE - if (con->smartenable || con->smartdisable || - con->smartautosaveenable || con->smartautosavedisable || - con->smartautoofflineenable || con->smartautoofflinedisable) + if ( options.smart_disable || options.smart_enable + || options.smart_auto_save_disable || options.smart_auto_save_enable + || options.smart_auto_offl_disable || options.smart_auto_offl_enable) pout("=== START OF ENABLE/DISABLE COMMANDS SECTION ===\n"); // Enable/Disable SMART commands - if (con->smartenable){ + if (options.smart_enable) { if (ataEnableSmart(device)) { pout("Smartctl: SMART Enable Failed.\n\n"); failuretest(MANDATORY_CMD, returnval|=FAILSMART); @@ -1857,7 +1858,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) } // Turn off SMART on device - if (con->smartdisable){ + if (options.smart_disable) { if (ataDisableSmart(device)) { pout( "Smartctl: SMART Disable Failed.\n\n"); failuretest(MANDATORY_CMD,returnval|=FAILSMART); @@ -1872,7 +1873,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) failuretest(MANDATORY_CMD, returnval|=FAILSMART); // Enable/Disable Auto-save attributes - if (con->smartautosaveenable){ + if (options.smart_auto_save_enable) { if (ataEnableAutoSave(device)){ pout( "Smartctl: SMART Enable Attribute Autosave Failed.\n\n"); failuretest(MANDATORY_CMD, returnval|=FAILSMART); @@ -1880,7 +1881,8 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) else pout("SMART Attribute Autosave Enabled.\n"); } - if (con->smartautosavedisable){ + + if (options.smart_auto_save_disable) { if (ataDisableAutoSave(device)){ pout( "Smartctl: SMART Disable Attribute Autosave Failed.\n\n"); failuretest(MANDATORY_CMD, returnval|=FAILSMART); @@ -1900,7 +1902,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) } // Enable/Disable Off-line testing - if (con->smartautoofflineenable){ + if (options.smart_auto_offl_enable) { if (!isSupportAutomaticTimer(&smartval)){ pout("Warning: device does not support SMART Automatic Timers.\n\n"); failuretest(OPTIONAL_CMD, returnval|=FAILSMART); @@ -1913,7 +1915,8 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) else pout("SMART Automatic Offline Testing Enabled every four hours.\n"); } - if (con->smartautoofflinedisable){ + + if (options.smart_auto_offl_disable) { if (!isSupportAutomaticTimer(&smartval)){ pout("Warning: device does not support SMART Automatic Timers.\n\n"); failuretest(OPTIONAL_CMD, returnval|=FAILSMART); @@ -1933,26 +1936,28 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) } // all this for a newline! - if (con->smartenable || con->smartdisable || - con->smartautosaveenable || con->smartautosavedisable || - con->smartautoofflineenable || con->smartautoofflinedisable) + if ( options.smart_disable || options.smart_enable + || options.smart_auto_save_disable || options.smart_auto_save_enable + || options.smart_auto_offl_disable || options.smart_auto_offl_enable) pout("\n"); // START OF READ-ONLY OPTIONS APART FROM -V and -i - if ( con->checksmart || con->generalsmartvalues || con->smartvendorattrib || con->smarterrorlog - || con->smartselftestlog || con->selectivetestlog || con->scttempsts || con->scttemphist - || options.smart_ext_error_log || options.smart_ext_selftest_log ) + if ( options.smart_check_status || options.smart_general_values + || options.smart_vendor_attrib || options.smart_error_log + || options.smart_selftest_log || options.smart_selective_selftest_log + || options.smart_ext_error_log || options.smart_ext_selftest_log + || options.sct_temp_sts || options.sct_temp_hist ) pout("=== START OF READ SMART DATA SECTION ===\n"); // Check SMART status (use previously returned value) - if (con->checksmart){ + if (options.smart_check_status) { switch (code) { case 0: // The case where the disk health is OK pout("SMART overall-health self-assessment test result: PASSED\n"); if (ataCheckSmart(&smartval, &smartthres,0)){ - if (con->smartvendorattrib) + if (options.smart_vendor_attrib) pout("See vendor-specific Attribute list for marginal Attributes.\n\n"); else { PRINT_ON(con); @@ -1973,7 +1978,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) PRINT_OFF(con); if (ataCheckSmart(&smartval, &smartthres,1)){ returnval|=FAILATTR; - if (con->smartvendorattrib) + if (options.smart_vendor_attrib) pout("See vendor-specific Attribute list for failed Attributes.\n\n"); else { PRINT_ON(con); @@ -1997,7 +2002,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) PRINT_OFF(con); returnval|=FAILATTR; returnval|=FAILSTATUS; - if (con->smartvendorattrib) + if (options.smart_vendor_attrib) pout("See vendor-specific Attribute list for failed Attributes.\n\n"); else { PRINT_ON(con); @@ -2008,7 +2013,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) else { pout("SMART overall-health self-assessment test result: PASSED\n"); if (ataCheckSmart(&smartval, &smartthres,0)){ - if (con->smartvendorattrib) + if (options.smart_vendor_attrib) pout("See vendor-specific Attribute list for marginal Attributes.\n\n"); else { PRINT_ON(con); @@ -2028,11 +2033,11 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) } // end of checking SMART Status // Print general SMART values - if (con->generalsmartvalues) + if (options.smart_general_values) PrintGeneralSmartValues(&smartval, &drive, fix_firmwarebug); // Print vendor-specific attributes - if (con->smartvendorattrib){ + if (options.smart_vendor_attrib) { PRINT_ON(con); PrintSmartAttribWithThres(&smartval, &smartthres, attributedefs, (con->printing_switchable ? 2 : 0)); @@ -2163,7 +2168,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) } // Print SMART error log - if (con->smarterrorlog){ + if (options.smart_error_log) { if (!isSmartErrorLogCapable(&smartval, &drive)){ pout("Warning: device does not support Error Logging\n"); failuretest(OPTIONAL_CMD, returnval|=FAILSMART); @@ -2198,7 +2203,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) } // Print SMART self-test log - if (con->smartselftestlog){ + if (options.smart_selftest_log) { if (!isSmartTestLogCapable(&smartval, &drive)){ pout("Warning: device does not support Self Test Logging\n"); failuretest(OPTIONAL_CMD, returnval|=FAILSMART); @@ -2217,7 +2222,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) } // Print SMART selective self-test log - if (con->selectivetestlog){ + if (options.smart_selective_selftest_log) { ata_selective_self_test_log log; if (!isSupportSelectiveSelfTest(&smartval)) @@ -2237,18 +2242,18 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) } } - // Print SMART SCT status and temperature history table - if (con->scttempsts || con->scttemphist || con->scttempint) { + // Print SCT status and temperature history table + if (options.sct_temp_sts || options.sct_temp_hist || options.sct_temp_int) { for (;;) { if (!isSCTCapable(&drive)) { pout("Warning: device does not support SCT Commands\n"); failuretest(OPTIONAL_CMD, returnval|=FAILSMART); break; } - if (con->scttempsts || con->scttemphist) { + if (options.sct_temp_sts || options.sct_temp_hist) { ata_sct_status_response sts; ata_sct_temperature_history_table tmh; - if (!con->scttemphist) { + if (!options.sct_temp_hist) { // Read SCT status only if (ataReadSCTStatus(device, &sts)) { failuretest(OPTIONAL_CMD, returnval|=FAILSMART); @@ -2267,25 +2272,26 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) break; } } - if (con->scttempsts) + if (options.sct_temp_sts) ataPrintSCTStatus(&sts); - if (con->scttemphist) + if (options.sct_temp_hist) ataPrintSCTTempHist(&tmh); pout("\n"); } - if (con->scttempint) { + if (options.sct_temp_int) { // Set new temperature logging interval if (!isSCTFeatureControlCapable(&drive)) { pout("Warning: device does not support SCT Feature Control command\n"); failuretest(OPTIONAL_CMD, returnval|=FAILSMART); break; } - if (ataSetSCTTempInterval(device, con->scttempint, !!con->scttempintp)) { + if (ataSetSCTTempInterval(device, options.sct_temp_int, options.sct_temp_int_pers)) { failuretest(OPTIONAL_CMD, returnval|=FAILSMART); break; } pout("Temperature Logging Interval set to %u minute%s (%s)\n", - con->scttempint, (con->scttempint==1?"":"s"), (con->scttempintp?"persistent":"volatile")); + options.sct_temp_int, (options.sct_temp_int == 1 ? "" : "s"), + (options.sct_temp_int_pers ? "persistent" : "volatile")); } break; } @@ -2302,12 +2308,12 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) } // START OF THE TESTING SECTION OF THE CODE. IF NO TESTING, RETURN - if (con->testcase==-1) + if (options.smart_selftest_type == -1) return returnval; pout("=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===\n"); // if doing a self-test, be sure it's supported by the hardware - switch (con->testcase){ + switch (options.smart_selftest_type) { case OFFLINE_FULL_SCAN: if (!isSupportExecuteOfflineImmediate(&smartval)){ pout("Warning: device does not support Execute Offline Immediate function.\n\n"); @@ -2339,14 +2345,14 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) } break; default: - pout("Internal error in smartctl: con->testcase==%d not recognized\n", (int)con->testcase); + pout("Internal error in smartctl: smart_test_type==%d not recognized\n", options.smart_selftest_type); pout("Please contact smartmontools developers at %s.\n", PACKAGE_BUGREPORT); EXIT(returnval|=FAILCMD); } // Now do the test. Note ataSmartTest prints its own error/success // messages - if (ataSmartTest(device, con->testcase, &smartval, get_num_sectors(&drive))) + if (ataSmartTest(device, options.smart_selftest_type, &smartval, get_num_sectors(&drive))) failuretest(OPTIONAL_CMD, returnval|=FAILSMART); else { // Tell user how long test will take to complete. This is tricky @@ -2354,7 +2360,7 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) // timer is volatile, and needs to be read AFTER the command is // given. If this will interrupt the Offline Full Scan, we don't // do it, just warn user. - if (con->testcase==OFFLINE_FULL_SCAN){ + if (options.smart_selftest_type == OFFLINE_FULL_SCAN) { if (isSupportOfflineAbort(&smartval)) pout("Note: giving further SMART commands will abort Offline testing\n"); else if (ataReadSmartValues(device, &smartval)){ @@ -2364,9 +2370,9 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) } // Now say how long the test will take to complete - if ((timewait=TestTime(&smartval,con->testcase))){ + if ((timewait = TestTime(&smartval, options.smart_selftest_type))) { time_t t=time(NULL); - if (con->testcase==OFFLINE_FULL_SCAN) { + if (options.smart_selftest_type == OFFLINE_FULL_SCAN) { t+=timewait; pout("Please wait %d seconds for test to complete.\n", (int)timewait); } else { @@ -2375,11 +2381,11 @@ int ataPrintMain (ata_device * device, const ata_print_options & options) } pout("Test will complete after %s\n", ctime(&t)); - if (con->testcase!=SHORT_CAPTIVE_SELF_TEST && - con->testcase!=EXTEND_CAPTIVE_SELF_TEST && - con->testcase!=CONVEYANCE_CAPTIVE_SELF_TEST && - con->testcase!=SELECTIVE_CAPTIVE_SELF_TEST) - pout("Use smartctl -X to abort test.\n"); + if ( options.smart_selftest_type != SHORT_CAPTIVE_SELF_TEST + && options.smart_selftest_type != EXTEND_CAPTIVE_SELF_TEST + && options.smart_selftest_type != CONVEYANCE_CAPTIVE_SELF_TEST + && options.smart_selftest_type != SELECTIVE_CAPTIVE_SELF_TEST ) + pout("Use smartctl -X to abort test.\n"); } } diff --git a/sm5/ataprint.h b/sm5/ataprint.h index e346bcf3eba5c9da8fe7346dc0a5cb81606f8425..d672fadfea56237d3da6479e38c425829841474e 100644 --- a/sm5/ataprint.h +++ b/sm5/ataprint.h @@ -26,7 +26,7 @@ #ifndef ATAPRINT_H_ #define ATAPRINT_H_ -#define ATAPRINT_H_CVSID "$Id: ataprint.h,v 1.40 2009/04/16 21:24:08 chrfranke Exp $\n" +#define ATAPRINT_H_CVSID "$Id: ataprint.h,v 1.41 2009/06/20 17:58:33 chrfranke Exp $\n" #include <vector> @@ -47,13 +47,32 @@ struct ata_log_request // TODO: Move remaining options from con->* to here. struct ata_print_options { - bool sataphy, sataphy_reset; + bool drive_info; + bool smart_check_status; + bool smart_general_values; + bool smart_vendor_attrib; + bool smart_error_log; + bool smart_selftest_log; + bool smart_selective_selftest_log; + bool gp_logdir, smart_logdir; unsigned smart_ext_error_log; unsigned smart_ext_selftest_log; std::vector<ata_log_request> log_requests; + bool sct_temp_sts, sct_temp_hist; + bool sataphy, sataphy_reset; + + bool smart_disable, smart_enable; + bool smart_auto_offl_disable, smart_auto_offl_enable; + bool smart_auto_save_disable, smart_auto_save_enable; + + int smart_selftest_type; // OFFLINE_FULL_SCAN, ..., see atacmds.h. -1 for no test + + unsigned sct_temp_int; + bool sct_temp_int_pers; + unsigned char fix_firmwarebug; // FIX_*, see atacmds.h bool fix_swapped_id; // Fix swapped ID strings returned by some buggy drivers @@ -67,16 +86,31 @@ struct ata_print_options bool ignore_presets; // Ignore presets from drive database bool show_presets; // Show presets and exit + unsigned char powermode; // Skip check, if disk in idle or standby mode ata_print_options() - : sataphy(false), sataphy_reset(false), + : drive_info(false), + smart_check_status(false), + smart_general_values(false), + smart_vendor_attrib(false), + smart_error_log(false), + smart_selftest_log(false), + smart_selective_selftest_log(false), gp_logdir(false), smart_logdir(false), smart_ext_error_log(0), smart_ext_selftest_log(0), + sct_temp_sts(false), sct_temp_hist(false), + sataphy(false), sataphy_reset(false), + smart_disable(false), smart_enable(false), + smart_auto_offl_disable(false), smart_auto_offl_enable(false), + smart_auto_save_disable(false), smart_auto_save_enable(false), + smart_selftest_type(-1), + sct_temp_int(0), sct_temp_int_pers(false), fix_firmwarebug(FIX_NOTSPECIFIED), fix_swapped_id(false), ignore_presets(false), - show_presets(false) + show_presets(false), + powermode(0) { memset(attributedefs, 0, sizeof(attributedefs)); } }; diff --git a/sm5/extern.h b/sm5/extern.h index 1f9c5217c5f9b8f69e2188989b6d4e758df8c55d..44743deb70f03c95c06bf1b6d3e52d8d357adfb1 100644 --- a/sm5/extern.h +++ b/sm5/extern.h @@ -3,7 +3,7 @@ * * Home page of code is: http://smartmontools.sourceforge.net * - * Copyright (C) 2002-8 Bruce Allen <smartmontools-support@lists.sourceforge.net> + * Copyright (C) 2002-9 Bruce Allen <smartmontools-support@lists.sourceforge.net> * Copyright (C) 1999-2000 Michael Cornwell <cornwell@acm.org> * * This program is free software; you can redistribute it and/or modify @@ -25,20 +25,19 @@ #ifndef EXTERN_H_ #define EXTERN_H_ -#define EXTERN_H_CVSID "$Id: extern.h,v 1.60 2009/04/16 21:24:08 chrfranke Exp $\n" +#define EXTERN_H_CVSID "$Id: extern.h,v 1.61 2009/06/20 17:58:33 chrfranke Exp $\n" // Block used for global control/communications. If you need more // global variables, this should be the only place that you need to // add them. typedef struct smartmonctrl_s { + // TODO: Use local struct for selective self test parameters // spans for selective self-test uint64_t smartselectivespan[5][2]; // mode for each span, see SEL_* in utility.h char smartselectivemode[5]; // number of spans int smartselectivenumspans; - int testcase; - unsigned scttempint; // one plus time in minutes to wait after powerup before restarting // interrupted offline scan after selective self-test. int pendingtime; @@ -46,36 +45,7 @@ typedef struct smartmonctrl_s { // turn off scan after selective self-test, 2: turn on scan after // selective self-test. unsigned char scanafterselect; - // skip check, if disk in idle or standby mode - unsigned char powermode; - unsigned char driveinfo; - unsigned char checksmart; - unsigned char smartvendorattrib; - unsigned char generalsmartvalues; - unsigned char smartselftestlog; - unsigned char selectivetestlog; - unsigned char smarterrorlog; - unsigned char smartbackgroundlog; - unsigned char scttempsts; - unsigned char scttemphist; - unsigned char scttempintp; - unsigned char smartdisable; - unsigned char smartenable; - unsigned char smartstatus; - unsigned char smartexeoffimmediate; - unsigned char smartshortselftest; - unsigned char smartextendselftest; - unsigned char smartconveyanceselftest; - unsigned char smartselectiveselftest; - unsigned char smartshortcapselftest; - unsigned char smartextendcapselftest; - unsigned char smartconveyancecapselftest; - unsigned char smartselectivecapselftest; - unsigned char smartselftestabort; - unsigned char smartautoofflineenable; - unsigned char smartautoofflinedisable; - unsigned char smartautosaveenable; - unsigned char smartautosavedisable; + unsigned char printing_switchable; unsigned char dont_print; unsigned char dont_print_serial; diff --git a/sm5/scsiprint.cpp b/sm5/scsiprint.cpp index 4698a8690cc0bb2fb50597040e81646afa4c1e35..a1df47597fd27a47c28488b551e249ef6069fa4e 100644 --- a/sm5/scsiprint.cpp +++ b/sm5/scsiprint.cpp @@ -44,7 +44,7 @@ #define GBUF_SIZE 65535 -const char* scsiprint_c_cvsid="$Id: scsiprint.cpp,v 1.126 2009/06/03 15:05:23 dpgilbert Exp $" +const char* scsiprint_c_cvsid="$Id: scsiprint.cpp,v 1.127 2009/06/20 17:58:33 chrfranke Exp $" CONFIG_H_CVSID EXTERN_H_CVSID INT64_H_CVSID SCSICMDS_H_CVSID SCSIPRINT_H_CVSID SMARTCTL_H_CVSID UTILITY_H_CVSID; // control block which points to external global control variables @@ -142,7 +142,7 @@ static void scsiGetSupportedLogPages(scsi_device * device) /* Returns 0 if ok, -1 if can't check IE, -2 if can check and bad (or at least something to report). */ -static int scsiGetSmartData(scsi_device * device, int attribs) +static int scsiGetSmartData(scsi_device * device, bool attribs) { UINT8 asc; UINT8 ascq; @@ -987,7 +987,7 @@ static const char * transport_proto_arr[] = { }; /* Returns 0 on success, 1 on general error and 2 for early, clean exit */ -static int scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, int all) +static int scsiGetDriveInfo(scsi_device * device, UINT8 * peripheral_type, bool all) { char manufacturer[9]; char product[17]; @@ -1237,14 +1237,14 @@ static void scsiPrintTemp(scsi_device * device) } /* Main entry point used by smartctl command. Return 0 for success */ -int scsiPrintMain(scsi_device * device) +int scsiPrintMain(scsi_device * device, const scsi_print_options & options) { int checkedSupportedLogPages = 0; UINT8 peripheral_type = 0; int returnval = 0; int res, durationSec; - res = scsiGetDriveInfo(device, &peripheral_type, con->driveinfo); + res = scsiGetDriveInfo(device, &peripheral_type, options.drive_info); if (res) { if (2 == res) return 0; @@ -1252,37 +1252,37 @@ int scsiPrintMain(scsi_device * device) failuretest(MANDATORY_CMD, returnval |= FAILID); } - if (con->smartenable) { + if (options.smart_enable) { if (scsiSmartEnable(device)) failuretest(MANDATORY_CMD, returnval |= FAILSMART); } - if (con->smartdisable) { + if (options.smart_disable) { if (scsiSmartDisable(device)) failuretest(MANDATORY_CMD,returnval |= FAILSMART); } - if (con->smartautosaveenable) { + if (options.smart_auto_save_enable) { if (scsiSetControlGLTSD(device, 0, modese_len)) { pout("Enable autosave (clear GLTSD bit) failed\n"); failuretest(OPTIONAL_CMD,returnval |= FAILSMART); } } - if (con->smartautosavedisable) { + if (options.smart_auto_save_disable) { if (scsiSetControlGLTSD(device, 1, modese_len)) { pout("Disable autosave (set GLTSD bit) failed\n"); failuretest(OPTIONAL_CMD,returnval |= FAILSMART); } } - if (con->checksmart) { + if (options.smart_check_status) { scsiGetSupportedLogPages(device); checkedSupportedLogPages = 1; if ((SCSI_PT_SEQUENTIAL_ACCESS == peripheral_type) || (SCSI_PT_MEDIUM_CHANGER == peripheral_type)) { /* tape device */ if (gTapeAlertsLPage) { - if (con->driveinfo) + if (options.drive_info) pout("TapeAlert Supported\n"); if (-1 == scsiGetTapeAlertsData(device, peripheral_type)) failuretest(OPTIONAL_CMD, returnval |= FAILSMART); @@ -1290,7 +1290,7 @@ int scsiPrintMain(scsi_device * device) else pout("TapeAlert Not Supported\n"); } else { /* disk, cd/dvd, enclosure, etc */ - if ((res = scsiGetSmartData(device, con->smartvendorattrib))) { + if ((res = scsiGetSmartData(device, options.smart_vendor_attrib))) { if (-2 == res) returnval |= FAILSTATUS; else @@ -1298,11 +1298,11 @@ int scsiPrintMain(scsi_device * device) } } } - if (con->smartvendorattrib) { + if (options.smart_vendor_attrib) { if (! checkedSupportedLogPages) scsiGetSupportedLogPages(device); if (gTempLPage) { - if (con->checksmart) + if (options.smart_check_status) pout("\n"); scsiPrintTemp(device); } @@ -1316,7 +1316,7 @@ int scsiPrintMain(scsi_device * device) scsiPrintSeagateFactoryLPage(device); } } - if (con->smarterrorlog) { + if (options.smart_error_log) { if (! checkedSupportedLogPages) scsiGetSupportedLogPages(device); scsiPrintErrorCounterLog(device); @@ -1324,7 +1324,7 @@ int scsiPrintMain(scsi_device * device) pout("\n[GLTSD (Global Logging Target Save Disable) set. " "Enable Save with '-S on']\n"); } - if (con->smartselftestlog) { + if (options.smart_selftest_log) { if (! checkedSupportedLogPages) scsiGetSupportedLogPages(device); res = 0; @@ -1337,7 +1337,7 @@ int scsiPrintMain(scsi_device * device) if (0 != res) failuretest(OPTIONAL_CMD, returnval|=res); } - if (con->smartbackgroundlog) { + if (options.smart_background_log) { if (! checkedSupportedLogPages) scsiGetSupportedLogPages(device); res = 0; @@ -1350,23 +1350,23 @@ int scsiPrintMain(scsi_device * device) if (0 != res) failuretest(OPTIONAL_CMD, returnval|=res); } - if (con->smartexeoffimmediate) { + if (options.smart_default_selftest) { if (scsiSmartDefaultSelfTest(device)) return returnval | FAILSMART; pout("Default Self Test Successful\n"); } - if (con->smartshortcapselftest) { + if (options.smart_short_cap_selftest) { if (scsiSmartShortCapSelfTest(device)) return returnval | FAILSMART; pout("Short Foreground Self Test Successful\n"); } - if (con->smartshortselftest ) { + if (options.smart_short_selftest) { if (scsiSmartShortSelfTest(device)) return returnval | FAILSMART; pout("Short Background Self Test has begun\n"); pout("Use smartctl -X to abort test\n"); } - if (con->smartextendselftest) { + if (options.smart_extend_selftest) { if (scsiSmartExtendSelfTest(device)) return returnval | FAILSMART; pout("Extended Background Self Test has begun\n"); @@ -1381,12 +1381,12 @@ int scsiPrintMain(scsi_device * device) } pout("Use smartctl -X to abort test\n"); } - if (con->smartextendcapselftest) { + if (options.smart_extend_cap_selftest) { if (scsiSmartExtendCapSelfTest(device)) return returnval | FAILSMART; pout("Extended Foreground Self Test Successful\n"); } - if (con->smartselftestabort) { + if (options.smart_selftest_abort) { if (scsiSmartSelfTestAbort(device)) return returnval | FAILSMART; pout("Self Test returned without error\n"); diff --git a/sm5/scsiprint.h b/sm5/scsiprint.h index 14dcea912a25fb6807ec60bfce43329a5165cd67..46a227568b5e8984b9118e2799e05a0c1353ae79 100644 --- a/sm5/scsiprint.h +++ b/sm5/scsiprint.h @@ -3,11 +3,11 @@ * * Home page of code is: http://smartmontools.sourceforge.net * - * Copyright (C) 2002-8 Bruce Allen <smartmontools-support@lists.sourceforge.net> + * Copyright (C) 2002-9 Bruce Allen <smartmontools-support@lists.sourceforge.net> * Copyright (C) 2000 Michael Cornwell <cornwell@acm.org> * * Additional SCSI work: - * Copyright (C) 2003-8 Douglas Gilbert <dougg@torque.net> + * Copyright (C) 2003-9 Douglas Gilbert <dougg@torque.net> * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,12 +26,46 @@ */ -/* scsismart version number */ #ifndef SCSI_PRINT_H_ #define SCSI_PRINT_H_ -#define SCSIPRINT_H_CVSID "$Id: scsiprint.h,v 1.22 2008/07/25 21:16:00 chrfranke Exp $\n" +#define SCSIPRINT_H_CVSID "$Id: scsiprint.h,v 1.23 2009/06/20 17:58:33 chrfranke Exp $\n" -int scsiPrintMain(scsi_device * device); +// Options for scsiPrintMain +// TODO: Move remaining options from con->* to here. +struct scsi_print_options +{ + bool drive_info; + bool smart_check_status; + bool smart_vendor_attrib; + bool smart_error_log; + bool smart_selftest_log; + bool smart_background_log; + + bool smart_disable, smart_enable; + bool smart_auto_save_disable, smart_auto_save_enable; + + bool smart_default_selftest; + bool smart_short_selftest, smart_short_cap_selftest; + bool smart_extend_selftest, smart_extend_cap_selftest; + bool smart_selftest_abort; + + scsi_print_options() + : drive_info(false), + smart_check_status(false), + smart_vendor_attrib(false), + smart_error_log(false), + smart_selftest_log(false), + smart_background_log(false), + smart_disable(false), smart_enable(false), + smart_auto_save_disable(false), smart_auto_save_enable(false), + smart_default_selftest(false), + smart_short_selftest(false), smart_short_cap_selftest(false), + smart_extend_selftest(false), smart_extend_cap_selftest(false), + smart_selftest_abort(false) + { } +}; + +int scsiPrintMain(scsi_device * device, const scsi_print_options & options); #endif diff --git a/sm5/smartctl.cpp b/sm5/smartctl.cpp index ba530dfbab8297b669b742bb2e150a8aa5eea146..81fa8ccbbc993b86ea2c4b5cc40d77fe4ccc73f4 100644 --- a/sm5/smartctl.cpp +++ b/sm5/smartctl.cpp @@ -63,7 +63,7 @@ extern const char *os_solaris_ata_s_cvsid; extern const char *cciss_c_cvsid; #endif 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; -const char* smartctl_c_cvsid="$Id: smartctl.cpp,v 1.197 2009/04/16 21:24:08 chrfranke Exp $" +const char* smartctl_c_cvsid="$Id: smartctl.cpp,v 1.198 2009/06/20 17:58:33 chrfranke Exp $" 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; // This is a block containing all the "control variables". We declare @@ -266,7 +266,9 @@ enum checksum_err_mode_t { static checksum_err_mode_t checksum_err_mode = CHECKSUM_ERR_WARN; /* Takes command options and sets features to be run */ -const char * ParseOpts (int argc, char** argv, ata_print_options & options) +const char * parse_options(int argc, char** argv, + ata_print_options & ataopts, + scsi_print_options & scsiopts) { int optchar; int badarg; @@ -309,12 +311,12 @@ const char * ParseOpts (int argc, char** argv, ata_print_options & options) memset(extraerror, 0, sizeof(extraerror)); memset(con,0,sizeof(*con)); - con->testcase=-1; opterr=optopt=0; badarg = captive = FALSE; const char * type = 0; // set to -d optarg bool no_defaultdb = false; // set true on '-B FILE' + int testcnt = 0; // number of self-tests requested // This miserable construction is needed to get emacs to do proper indenting. Sorry! while (-1 != (optchar = @@ -395,86 +397,86 @@ const char * ParseOpts (int argc, char** argv, ata_print_options & options) break; case 's': if (!strcmp(optarg,"on")) { - con->smartenable = TRUE; - con->smartdisable = FALSE; + ataopts.smart_enable = scsiopts.smart_enable = true; + ataopts.smart_disable = scsiopts.smart_disable = false; } else if (!strcmp(optarg,"off")) { - con->smartdisable = TRUE; - con->smartenable = FALSE; + ataopts.smart_disable = scsiopts.smart_disable = true; + ataopts.smart_enable = scsiopts.smart_enable = false; } else { badarg = TRUE; } break; case 'o': if (!strcmp(optarg,"on")) { - con->smartautoofflineenable = TRUE; - con->smartautoofflinedisable = FALSE; + ataopts.smart_auto_offl_enable = true; + ataopts.smart_auto_offl_disable = false; } else if (!strcmp(optarg,"off")) { - con->smartautoofflinedisable = TRUE; - con->smartautoofflineenable = FALSE; + ataopts.smart_auto_offl_disable = true; + ataopts.smart_auto_offl_enable = false; } else { badarg = TRUE; } break; case 'S': if (!strcmp(optarg,"on")) { - con->smartautosaveenable = TRUE; - con->smartautosavedisable = FALSE; + ataopts.smart_auto_save_enable = scsiopts.smart_auto_save_enable = true; + ataopts.smart_auto_save_disable = scsiopts.smart_auto_save_disable = false; } else if (!strcmp(optarg,"off")) { - con->smartautosavedisable = TRUE; - con->smartautosaveenable = FALSE; + ataopts.smart_auto_save_disable = scsiopts.smart_auto_save_disable = true; + ataopts.smart_auto_save_enable = scsiopts.smart_auto_save_enable = false; } else { badarg = TRUE; } break; case 'H': - con->checksmart = TRUE; + ataopts.smart_check_status = scsiopts.smart_check_status = true; break; case 'F': if (!strcmp(optarg,"none")) { - options.fix_firmwarebug = FIX_NONE; + ataopts.fix_firmwarebug = FIX_NONE; } else if (!strcmp(optarg,"samsung")) { - options.fix_firmwarebug = FIX_SAMSUNG; + ataopts.fix_firmwarebug = FIX_SAMSUNG; } else if (!strcmp(optarg,"samsung2")) { - options.fix_firmwarebug = FIX_SAMSUNG2; + ataopts.fix_firmwarebug = FIX_SAMSUNG2; } else if (!strcmp(optarg,"samsung3")) { - options.fix_firmwarebug = FIX_SAMSUNG3; + ataopts.fix_firmwarebug = FIX_SAMSUNG3; } else if (!strcmp(optarg,"swapid")) { - options.fix_swapped_id = true; + ataopts.fix_swapped_id = true; } else { badarg = TRUE; } break; case 'c': - con->generalsmartvalues = TRUE; + ataopts.smart_general_values = true; break; case 'A': - con->smartvendorattrib = TRUE; + ataopts.smart_vendor_attrib = scsiopts.smart_vendor_attrib = true; break; case 'l': if (!strcmp(optarg,"error")) { - con->smarterrorlog = TRUE; + ataopts.smart_error_log = scsiopts.smart_error_log = true; } else if (!strcmp(optarg,"selftest")) { - con->smartselftestlog = TRUE; + ataopts.smart_selftest_log = scsiopts.smart_selftest_log = true; } else if (!strcmp(optarg, "selective")) { - con->selectivetestlog = TRUE; + ataopts.smart_selective_selftest_log = true; } else if (!strcmp(optarg,"directory")) { - options.smart_logdir = options.gp_logdir = true; // SMART+GPL + ataopts.smart_logdir = ataopts.gp_logdir = true; // SMART+GPL } else if (!strcmp(optarg,"directory,s")) { - options.smart_logdir = true; // SMART + ataopts.smart_logdir = true; // SMART } else if (!strcmp(optarg,"directory,g")) { - options.gp_logdir = true; // GPL + ataopts.gp_logdir = true; // GPL } else if (!strcmp(optarg,"sataphy")) { - options.sataphy = true; + ataopts.sataphy = true; } else if (!strcmp(optarg,"sataphy,reset")) { - options.sataphy = options.sataphy_reset = true; + ataopts.sataphy = ataopts.sataphy_reset = true; } else if (!strcmp(optarg,"background")) { - con->smartbackgroundlog = TRUE; + scsiopts.smart_background_log = true; } else if (!strcmp(optarg,"scttemp")) { - con->scttempsts = con->scttemphist = TRUE; + ataopts.sct_temp_sts = ataopts.sct_temp_hist = true; } else if (!strcmp(optarg,"scttempsts")) { - con->scttempsts = TRUE; + ataopts.sct_temp_sts = true; } else if (!strcmp(optarg,"scttemphist")) { - con->scttemphist = TRUE; + ataopts.sct_temp_hist = true; } else if ( !strncmp(optarg,"xerror" , sizeof("xerror" )-1) || !strncmp(optarg,"xselftest", sizeof("xselftest")-1)) { @@ -484,9 +486,9 @@ const char * ParseOpts (int argc, char** argv, ata_print_options & options) if (!((n1 == len || n2 == len) && val > 0)) badarg = TRUE; else if (optarg[1] == 'e') - options.smart_ext_error_log = val; + ataopts.smart_ext_error_log = val; else - options.smart_ext_selftest_log = val; + ataopts.smart_ext_selftest_log = val; } else if ( !strncmp(optarg, "gplog," , sizeof("gplog," )-1) || !strncmp(optarg, "smartlog,", sizeof("smartlog,")-1)) { @@ -515,24 +517,24 @@ const char * ParseOpts (int argc, char** argv, ata_print_options & options) ata_log_request req; req.gpl = gpl; req.logaddr = logaddr; req.page = page; req.nsectors = (sign == '-' ? nsectors-page+1 : nsectors); - options.log_requests.push_back(req); + ataopts.log_requests.push_back(req); } } else { badarg = TRUE; } break; case 'i': - con->driveinfo = TRUE; - break; + ataopts.drive_info = scsiopts.drive_info = true; + break; case 'a': - con->driveinfo = TRUE; - con->checksmart = TRUE; - con->generalsmartvalues = TRUE; - con->smartvendorattrib = TRUE; - con->smarterrorlog = TRUE; - con->smartselftestlog = TRUE; - con->selectivetestlog = TRUE; - /* con->smartbackgroundlog = TRUE; */ + ataopts.drive_info = scsiopts.drive_info = true; + ataopts.smart_check_status = scsiopts.smart_check_status = true; + ataopts.smart_general_values = true; + ataopts.smart_vendor_attrib = scsiopts.smart_vendor_attrib = true; + ataopts.smart_error_log = scsiopts.smart_error_log = true; + ataopts.smart_selftest_log = scsiopts.smart_selftest_log = true; + ataopts.smart_selective_selftest_log = true; + /* scsiopts.smart_background_log = true; */ break; case 'v': // parse vendor-specific definitions of attributes @@ -543,16 +545,16 @@ const char * ParseOpts (int argc, char** argv, ata_print_options & options) create_vendor_attribute_arg_list().c_str()); EXIT(0); } - if (parse_attribute_def(optarg, options.attributedefs)) + if (parse_attribute_def(optarg, ataopts.attributedefs)) badarg = TRUE; break; case 'P': if (!strcmp(optarg, "use")) { - options.ignore_presets = false; + ataopts.ignore_presets = false; } else if (!strcmp(optarg, "ignore")) { - options.ignore_presets = true; + ataopts.ignore_presets = true; } else if (!strcmp(optarg, "show")) { - options.show_presets = true; + ataopts.show_presets = true; } else if (!strcmp(optarg, "showall")) { if (!no_defaultdb && !read_default_drive_databases()) EXIT(FAILCMD); @@ -569,17 +571,20 @@ const char * ParseOpts (int argc, char** argv, ata_print_options & options) break; case 't': if (!strcmp(optarg,"offline")) { - con->smartexeoffimmediate = TRUE; - con->testcase = OFFLINE_FULL_SCAN; + testcnt++; + ataopts.smart_selftest_type = OFFLINE_FULL_SCAN; + scsiopts.smart_default_selftest = true; } else if (!strcmp(optarg,"short")) { - con->smartshortselftest = TRUE; - con->testcase = SHORT_SELF_TEST; + testcnt++; + ataopts.smart_selftest_type = SHORT_SELF_TEST; + scsiopts.smart_short_selftest = true; } else if (!strcmp(optarg,"long")) { - con->smartextendselftest = TRUE; - con->testcase = EXTEND_SELF_TEST; + testcnt++; + ataopts.smart_selftest_type = EXTEND_SELF_TEST; + scsiopts.smart_extend_selftest = true; } else if (!strcmp(optarg,"conveyance")) { - con->smartconveyanceselftest = TRUE; - con->testcase = CONVEYANCE_SELF_TEST; + testcnt++; + ataopts.smart_selftest_type = CONVEYANCE_SELF_TEST; } else if (!strcmp(optarg,"afterselect,on")) { // scan remainder of disk after doing selected segments con->scanafterselect=2; @@ -602,6 +607,7 @@ const char * ParseOpts (int argc, char** argv, ata_print_options & options) con->pendingtime=i+1; } } else if (!strncmp(optarg,"select",strlen("select"))) { + testcnt++; // parse range of LBAs to test uint64_t start, stop; int mode; if (split_selective_arg(optarg, &start, &stop, &mode)) { @@ -622,7 +628,7 @@ const char * ParseOpts (int argc, char** argv, ata_print_options & options) con->smartselectivespan[con->smartselectivenumspans][1] = stop; con->smartselectivemode[con->smartselectivenumspans] = mode; con->smartselectivenumspans++; - con->testcase = SELECTIVE_SELF_TEST; + ataopts.smart_selftest_type = SELECTIVE_SELF_TEST; } } else if (!strncmp(optarg, "scttempint,", sizeof("scstempint,")-1)) { unsigned interval = 0; int n1 = -1, n2 = -1, len = strlen(optarg); @@ -631,8 +637,8 @@ const char * ParseOpts (int argc, char** argv, ata_print_options & options) strcpy(extraerror, "Option -t scttempint,N[,p] must have positive integer N\n"); badarg = TRUE; } - con->scttempint = interval; - con->scttempintp = (n2 == len); + ataopts.sct_temp_int = interval; + ataopts.sct_temp_int_pers = (n2 == len); } else { badarg = TRUE; } @@ -641,19 +647,20 @@ const char * ParseOpts (int argc, char** argv, ata_print_options & options) captive = TRUE; break; case 'X': - con->smartselftestabort = TRUE; - con->testcase = ABORT_SELF_TEST; + testcnt++; + scsiopts.smart_selftest_abort = true; + ataopts.smart_selftest_type = ABORT_SELF_TEST; break; case 'n': // skip disk check if in low-power mode if (!strcmp(optarg, "never")) - con->powermode = 1; // do not skip, but print mode + ataopts.powermode = 1; // do not skip, but print mode else if (!strcmp(optarg, "sleep")) - con->powermode = 2; + ataopts.powermode = 2; else if (!strcmp(optarg, "standby")) - con->powermode = 3; + ataopts.powermode = 3; else if (!strcmp(optarg, "idle")) - con->powermode = 4; + ataopts.powermode = 4; else badarg = TRUE; break; @@ -732,8 +739,7 @@ const char * ParseOpts (int argc, char** argv, ata_print_options & options) con->dont_print=TRUE; // error message if user has asked for more than one test - if (1<(con->smartexeoffimmediate+con->smartshortselftest+con->smartextendselftest+ - con->smartshortcapselftest+con->smartextendcapselftest+con->smartselftestabort + (con->smartselectivenumspans>0?1:0))){ + if (testcnt > 1) { con->dont_print=FALSE; printslogan(); pout("\nERROR: smartctl can only run a single test type (or abort) at a time.\n"); @@ -755,26 +761,26 @@ const char * ParseOpts (int argc, char** argv, ata_print_options & options) } // If captive option was used, change test type if appropriate. - if (captive && con->smartshortselftest) { - con->smartshortselftest = FALSE; - con->smartshortcapselftest = TRUE; - con->testcase = SHORT_CAPTIVE_SELF_TEST; - } else if (captive && con->smartextendselftest) { - con->smartextendselftest = FALSE; - con->smartextendcapselftest = TRUE; - con->testcase = EXTEND_CAPTIVE_SELF_TEST; - } - else if (captive && con->smartconveyanceselftest) { - con->smartconveyanceselftest = FALSE; - con->smartconveyancecapselftest = TRUE; - con->testcase = CONVEYANCE_CAPTIVE_SELF_TEST; - } - else if (captive && con->smartselectiveselftest) { - con->smartselectiveselftest = FALSE; - con->smartselectivecapselftest = TRUE; - con->testcase = SELECTIVE_CAPTIVE_SELF_TEST; - } - + if (captive) + switch (ataopts.smart_selftest_type) { + case SHORT_SELF_TEST: + ataopts.smart_selftest_type = SHORT_CAPTIVE_SELF_TEST; + scsiopts.smart_short_selftest = false; + scsiopts.smart_short_cap_selftest = true; + break; + case EXTEND_SELF_TEST: + ataopts.smart_selftest_type = EXTEND_CAPTIVE_SELF_TEST; + scsiopts.smart_extend_selftest = false; + scsiopts.smart_extend_cap_selftest = true; + break; + case CONVEYANCE_SELF_TEST: + ataopts.smart_selftest_type = CONVEYANCE_CAPTIVE_SELF_TEST; + break; + case SELECTIVE_SELF_TEST: + ataopts.smart_selftest_type = SELECTIVE_CAPTIVE_SELF_TEST; + break; + } + // From here on, normal operations... printslogan(); @@ -885,8 +891,9 @@ int main_worker(int argc, char **argv) con=&control; // Parse input arguments - ata_print_options options; - const char * type = ParseOpts(argc, argv, options); + ata_print_options ataopts; + scsi_print_options scsiopts; + const char * type = parse_options(argc, argv, ataopts, scsiopts); // '-d test' -> Report result of autodetection bool print_type_only = (type && !strcmp(type, "test")); @@ -947,9 +954,9 @@ int main_worker(int argc, char **argv) pout("%s: Device of type '%s' [%s] opened\n", dev->get_info_name(), dev->get_dev_type(), get_protocol_info(dev)); else if (dev->is_ata()) - retval = ataPrintMain(dev->to_ata(), options); + retval = ataPrintMain(dev->to_ata(), ataopts); else if (dev->is_scsi()) - retval = scsiPrintMain(dev->to_scsi()); + retval = scsiPrintMain(dev->to_scsi(), scsiopts); else // we should never fall into this branch! pout("%s: Neither ATA nor SCSI device\n", dev->get_info_name());