diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG index 834f014f3cd944b86307759724f60fe04b9c59b0..0a7c02ab00e97034f92933751c2c5c7664d07333 100644 --- a/sm5/CHANGELOG +++ b/sm5/CHANGELOG @@ -1,6 +1,6 @@ CHANGELOG for smartmontools -$Id: CHANGELOG,v 1.13 2002/10/22 11:40:52 ballen4705 Exp $ +$Id: CHANGELOG,v 1.14 2002/10/22 16:49:15 ballen4705 Exp $ Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> @@ -29,6 +29,16 @@ NOTES FOR NEXT RELEASE: smartmontools-5.0-11 + smartctl now returns sensible values (bitmask). See smartctl.h + for the values. I may add some additional values as time goes on, + so this is prelimiary. + + The SMART status check now uses the correct ATA call. If failure + is detected we search through attributes to list the failed ones. + If the SMART status check shows GOOD, we then look to see if their + are any usage attributes or prefail attributes have failed at any + time. If so we print them. + Modified function that prints vendor attributes to say if the attribute has currently failed or has ever failed. diff --git a/sm5/ataprint.c b/sm5/ataprint.c index 41bbcde8ff7d822276349f8c5eba6d2675285b75..d946656d38de67899925546ec760235d8700aed8 100644 --- a/sm5/ataprint.c +++ b/sm5/ataprint.c @@ -28,7 +28,7 @@ #include "smartctl.h" #include "extern.h" -const char *CVSid4="$Id: ataprint.c,v 1.22 2002/10/22 15:37:15 ballen4705 Exp $\n" +const char *CVSid4="$Id: ataprint.c,v 1.23 2002/10/22 16:49:16 ballen4705 Exp $\n" "\t" CVSID2 "\t" CVSID3 "\t" CVSID6 ; // Function for printing ASCII byte-swapped strings, skipping white @@ -401,7 +401,7 @@ void PrintSmartAttribWithThres (struct ata_smart_values data, // is this currently failed, or has it ever failed? if (failednow) - status="FAILED NOW!"; + status="FAILED_NOW!"; else if (failedever) status="In_the_past"; else @@ -412,7 +412,7 @@ void PrintSmartAttribWithThres (struct ata_smart_values data, // printing line for each valid attribute type=disk->status.flag.prefailure?"Pre-fail":"Old_age"; - printf(" 0x%04x %.3i %.3i %.3i %-9s%-13s", + printf(" 0x%04x %.3i %.3i %.3i %-9s%-12s", disk->status.all, disk->current, disk->worst, thre->threshold, type, status); @@ -819,13 +819,15 @@ struct ata_smart_thresholds smartthres; struct ata_smart_errorlog smarterror; struct ata_smart_selftestlog smartselftest; -void ataPrintMain (int fd){ +int ataPrintMain (int fd){ int timewait,code; + int returnval=0; // Start by getting Drive ID information. We need this, to know if SMART is supported. if (ataReadHDIdentity(fd,&drive)){ printf("Smartctl: Hard Drive Read Identity Failed\n\n"); - } + returnval|=FAILID; +} // Print most drive identity information if requested if (driveinfo){ @@ -839,7 +841,7 @@ void ataPrintMain (int fd){ printf(" Checking to be sure by trying SMART ENABLE command.\n"); if (ataEnableSmart(fd)){ printf(" No SMART functionality found. Sorry.\n"); - exit(0); + return returnval|FAILSMART; } else printf(" SMART appears to work. Continuing.\n"); @@ -864,6 +866,7 @@ void ataPrintMain (int fd){ if (smartenable){ if (ataEnableSmart(fd)) { printf("Smartctl: SMART Enable Failed.\n\n"); + returnval|=FAILSMART; } else printf("SMART Enabled.\n"); @@ -872,56 +875,72 @@ void ataPrintMain (int fd){ // From here on, every command requires that SMART be enabled... if (!ataDoesSmartWork(fd)) { printf("SMART Disabled. Use option -%c to enable it.\n", SMARTENABLE ); - exit(0); + return returnval; } // Turn off SMART on device if (smartdisable){ if (ataDisableSmart(fd)) { printf( "Smartctl: SMART Disable Failed.\n\n"); + returnval|=FAILSMART; } printf("SMART Disabled. Use option -%c to enable it.\n",SMARTENABLE); - exit (0); + return returnval; } // Let's ALWAYS issue this command to get the SMART status code=ataSmartStatus2(fd); - + if (code==-1) + returnval|=FAILSMART; + // Enable/Disable Auto-save attributes if (smartautosaveenable){ - if (ataEnableAutoSave(fd)) + if (ataEnableAutoSave(fd)){ printf( "Smartctl: SMART Enable Attribute Autosave Failed.\n\n"); + returnval|=FAILSMART; + } else printf("SMART Attribute Autosave Enabled.\n"); } if (smartautosavedisable){ - if (ataDisableAutoSave(fd)) + if (ataDisableAutoSave(fd)){ printf( "Smartctl: SMART Disable Attribute Autosave Failed.\n\n"); + returnval|=FAILSMART; + } else printf("SMART Attribute Autosave Disabled.\n"); } // for everything else read values and thresholds are needed - if (ataReadSmartValues(fd, &smartval)) + if (ataReadSmartValues(fd, &smartval)){ printf("Smartctl: SMART Values Read Failed.\n\n"); - if (ataReadSmartThresholds(fd, &smartthres)) + returnval|=FAILSMART; + } + if (ataReadSmartThresholds(fd, &smartthres)){ printf("Smartctl: SMART Thresholds Read Failed.\n\n"); - + returnval|=FAILSMART; + } + // Enable/Disable Off-line testing if (smartautoofflineenable){ - if (!isSupportAutomaticTimer (smartval)){ + if (!isSupportAutomaticTimer(smartval)){ printf("Device does not support SMART Automatic Timers.\n\n"); } - if (ataEnableAutoOffline (fd)) + if (ataEnableAutoOffline(fd)){ printf( "Smartctl: SMART Enable Automatic Offline Failed.\n\n"); + returnval|=FAILSMART; + } else printf ("SMART Automatic Offline Testing Enabled every four hours.\n"); } if (smartautoofflinedisable){ - if (!isSupportAutomaticTimer (smartval)) - printf("Device does not support SMART Automatic Timers.\n\n"); - if (ataDisableAutoOffline (fd)) + if (!isSupportAutomaticTimer(smartval)){ + printf("Device does not support SMART Automatic Timers.\n\n"); + } + if (ataDisableAutoOffline(fd)){ printf("Smartctl: SMART Disable Automatic Offline Failed.\n\n"); + returnval|=FAILSMART; + } else printf("SMART Automatic Offline Testing Disabled.\n"); } @@ -936,25 +955,24 @@ void ataPrintMain (int fd){ printf("SMART overall-health self-assessment test result: FAILED!\n" "Drive failure expected in less than 24 hours. SAVE ALL DATA\n"); if (ataCheckSmart(smartval, smartthres,1)){ - printf("SMART prefailure attributes shown below are below threshold.\n" - "Use -%c option to investigate\n",SMARTVENDORATTRIB); - - printf("Below is a list of failing attributes.\nUse -%c option to investigate.\n", - SMARTVENDORATTRIB); + returnval|=FAILATTR; + printf("Failed attributes:\n"); PrintSmartAttribWithThres(smartval, smartthres,1); - printf("\n"); } - else - printf("Unable to confirm any failing attributes.\n"); + else { + printf("No failing attributes found.\n"); + } + printf("\n"); + returnval|=FAILSTATUS; } else { printf("SMART overall-health self-assessment test result: PASSED\n"); if (ataCheckSmart(smartval, smartthres,0)){ - printf("Note: SMART attributes shown below are below threshold now or were in the past.\n" - "Use -%c option to investigate\n",SMARTVENDORATTRIB); + printf("Marginal attributes:\n"); PrintSmartAttribWithThres(smartval, smartthres,2); - printf("\n"); + returnval|=FAILAGE; } + printf("\n"); } } @@ -965,26 +983,34 @@ void ataPrintMain (int fd){ // Print vendor-specific attributes if (smartvendorattrib) PrintSmartAttribWithThres(smartval, smartthres,0); - + // Print SMART error log if (smarterrorlog){ - if (!isSmartErrorLogCapable(smartval)) + if (!isSmartErrorLogCapable(smartval)){ printf("Device does not support Error Logging\n"); + returnval|=FAILSMART; + } else { - if (ataReadErrorLog(fd, &smarterror)) + if (ataReadErrorLog(fd, &smarterror)){ printf("Smartctl: SMART Errorlog Read Failed\n"); + returnval|=FAILSMART; + } else ataPrintSmartErrorlog(smarterror); } } - + // Print SMART self-test log if (smartselftestlog){ - if (!isSmartErrorLogCapable(smartval)) + if (!isSmartErrorLogCapable(smartval)){ printf("Device does not support Self Test Logging\n"); + returnval|=FAILSMART; + } else { - if(ataReadSelfTestLog(fd, &smartselftest)) + if(ataReadSelfTestLog(fd, &smartselftest)){ printf("Smartctl: SMART Self Test Log Read Failed\n"); + returnval|=FAILSMART; + } else ataPrintSmartSelfTestlog(smartselftest); } @@ -992,24 +1018,23 @@ void ataPrintMain (int fd){ // START OF THE TESTING SECTION OF THE CODE. IF NO TESTING, RETURN if (testcase==-1) - return; + return returnval; printf("\n=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===\n"); - // if doing a self-test, be sure it's supported by the hardware if (testcase==OFFLINE_FULL_SCAN && !isSupportExecuteOfflineImmediate(smartval)){ printf("ERROR: device does not support Execute Off-Line Immediate function.\n\n"); - exit(-1); + return returnval|=FAILSMART; } else if (!isSupportSelfTest(smartval)){ printf ("ERROR: device does not support Self-Test functions.\n\n"); - exit(-1); + return returnval|=FAILSMART; } // Now do the test if (ataSmartTest(fd, testcase)) - exit(-1); + return returnval|=FAILSMART; // Tell user how long test will take to complete if ((timewait=TestTime(smartval,testcase))){ @@ -1019,5 +1044,5 @@ void ataPrintMain (int fd){ if (testcase!=SHORT_CAPTIVE_SELF_TEST && testcase!=EXTEND_CAPTIVE_SELF_TEST) printf ("Use smartctl -%c to abort test.\n", SMARTSELFTESTABORT); } - return; + return returnval; } diff --git a/sm5/ataprint.cpp b/sm5/ataprint.cpp index c856e73aa7d3f05e9170c01678dc27fad122ac96..b0a492e29bc680c4839c4a6ffad4fdb9de0c7b0b 100644 --- a/sm5/ataprint.cpp +++ b/sm5/ataprint.cpp @@ -28,7 +28,7 @@ #include "smartctl.h" #include "extern.h" -const char *CVSid4="$Id: ataprint.cpp,v 1.22 2002/10/22 15:37:15 ballen4705 Exp $\n" +const char *CVSid4="$Id: ataprint.cpp,v 1.23 2002/10/22 16:49:16 ballen4705 Exp $\n" "\t" CVSID2 "\t" CVSID3 "\t" CVSID6 ; // Function for printing ASCII byte-swapped strings, skipping white @@ -401,7 +401,7 @@ void PrintSmartAttribWithThres (struct ata_smart_values data, // is this currently failed, or has it ever failed? if (failednow) - status="FAILED NOW!"; + status="FAILED_NOW!"; else if (failedever) status="In_the_past"; else @@ -412,7 +412,7 @@ void PrintSmartAttribWithThres (struct ata_smart_values data, // printing line for each valid attribute type=disk->status.flag.prefailure?"Pre-fail":"Old_age"; - printf(" 0x%04x %.3i %.3i %.3i %-9s%-13s", + printf(" 0x%04x %.3i %.3i %.3i %-9s%-12s", disk->status.all, disk->current, disk->worst, thre->threshold, type, status); @@ -819,13 +819,15 @@ struct ata_smart_thresholds smartthres; struct ata_smart_errorlog smarterror; struct ata_smart_selftestlog smartselftest; -void ataPrintMain (int fd){ +int ataPrintMain (int fd){ int timewait,code; + int returnval=0; // Start by getting Drive ID information. We need this, to know if SMART is supported. if (ataReadHDIdentity(fd,&drive)){ printf("Smartctl: Hard Drive Read Identity Failed\n\n"); - } + returnval|=FAILID; +} // Print most drive identity information if requested if (driveinfo){ @@ -839,7 +841,7 @@ void ataPrintMain (int fd){ printf(" Checking to be sure by trying SMART ENABLE command.\n"); if (ataEnableSmart(fd)){ printf(" No SMART functionality found. Sorry.\n"); - exit(0); + return returnval|FAILSMART; } else printf(" SMART appears to work. Continuing.\n"); @@ -864,6 +866,7 @@ void ataPrintMain (int fd){ if (smartenable){ if (ataEnableSmart(fd)) { printf("Smartctl: SMART Enable Failed.\n\n"); + returnval|=FAILSMART; } else printf("SMART Enabled.\n"); @@ -872,56 +875,72 @@ void ataPrintMain (int fd){ // From here on, every command requires that SMART be enabled... if (!ataDoesSmartWork(fd)) { printf("SMART Disabled. Use option -%c to enable it.\n", SMARTENABLE ); - exit(0); + return returnval; } // Turn off SMART on device if (smartdisable){ if (ataDisableSmart(fd)) { printf( "Smartctl: SMART Disable Failed.\n\n"); + returnval|=FAILSMART; } printf("SMART Disabled. Use option -%c to enable it.\n",SMARTENABLE); - exit (0); + return returnval; } // Let's ALWAYS issue this command to get the SMART status code=ataSmartStatus2(fd); - + if (code==-1) + returnval|=FAILSMART; + // Enable/Disable Auto-save attributes if (smartautosaveenable){ - if (ataEnableAutoSave(fd)) + if (ataEnableAutoSave(fd)){ printf( "Smartctl: SMART Enable Attribute Autosave Failed.\n\n"); + returnval|=FAILSMART; + } else printf("SMART Attribute Autosave Enabled.\n"); } if (smartautosavedisable){ - if (ataDisableAutoSave(fd)) + if (ataDisableAutoSave(fd)){ printf( "Smartctl: SMART Disable Attribute Autosave Failed.\n\n"); + returnval|=FAILSMART; + } else printf("SMART Attribute Autosave Disabled.\n"); } // for everything else read values and thresholds are needed - if (ataReadSmartValues(fd, &smartval)) + if (ataReadSmartValues(fd, &smartval)){ printf("Smartctl: SMART Values Read Failed.\n\n"); - if (ataReadSmartThresholds(fd, &smartthres)) + returnval|=FAILSMART; + } + if (ataReadSmartThresholds(fd, &smartthres)){ printf("Smartctl: SMART Thresholds Read Failed.\n\n"); - + returnval|=FAILSMART; + } + // Enable/Disable Off-line testing if (smartautoofflineenable){ - if (!isSupportAutomaticTimer (smartval)){ + if (!isSupportAutomaticTimer(smartval)){ printf("Device does not support SMART Automatic Timers.\n\n"); } - if (ataEnableAutoOffline (fd)) + if (ataEnableAutoOffline(fd)){ printf( "Smartctl: SMART Enable Automatic Offline Failed.\n\n"); + returnval|=FAILSMART; + } else printf ("SMART Automatic Offline Testing Enabled every four hours.\n"); } if (smartautoofflinedisable){ - if (!isSupportAutomaticTimer (smartval)) - printf("Device does not support SMART Automatic Timers.\n\n"); - if (ataDisableAutoOffline (fd)) + if (!isSupportAutomaticTimer(smartval)){ + printf("Device does not support SMART Automatic Timers.\n\n"); + } + if (ataDisableAutoOffline(fd)){ printf("Smartctl: SMART Disable Automatic Offline Failed.\n\n"); + returnval|=FAILSMART; + } else printf("SMART Automatic Offline Testing Disabled.\n"); } @@ -936,25 +955,24 @@ void ataPrintMain (int fd){ printf("SMART overall-health self-assessment test result: FAILED!\n" "Drive failure expected in less than 24 hours. SAVE ALL DATA\n"); if (ataCheckSmart(smartval, smartthres,1)){ - printf("SMART prefailure attributes shown below are below threshold.\n" - "Use -%c option to investigate\n",SMARTVENDORATTRIB); - - printf("Below is a list of failing attributes.\nUse -%c option to investigate.\n", - SMARTVENDORATTRIB); + returnval|=FAILATTR; + printf("Failed attributes:\n"); PrintSmartAttribWithThres(smartval, smartthres,1); - printf("\n"); } - else - printf("Unable to confirm any failing attributes.\n"); + else { + printf("No failing attributes found.\n"); + } + printf("\n"); + returnval|=FAILSTATUS; } else { printf("SMART overall-health self-assessment test result: PASSED\n"); if (ataCheckSmart(smartval, smartthres,0)){ - printf("Note: SMART attributes shown below are below threshold now or were in the past.\n" - "Use -%c option to investigate\n",SMARTVENDORATTRIB); + printf("Marginal attributes:\n"); PrintSmartAttribWithThres(smartval, smartthres,2); - printf("\n"); + returnval|=FAILAGE; } + printf("\n"); } } @@ -965,26 +983,34 @@ void ataPrintMain (int fd){ // Print vendor-specific attributes if (smartvendorattrib) PrintSmartAttribWithThres(smartval, smartthres,0); - + // Print SMART error log if (smarterrorlog){ - if (!isSmartErrorLogCapable(smartval)) + if (!isSmartErrorLogCapable(smartval)){ printf("Device does not support Error Logging\n"); + returnval|=FAILSMART; + } else { - if (ataReadErrorLog(fd, &smarterror)) + if (ataReadErrorLog(fd, &smarterror)){ printf("Smartctl: SMART Errorlog Read Failed\n"); + returnval|=FAILSMART; + } else ataPrintSmartErrorlog(smarterror); } } - + // Print SMART self-test log if (smartselftestlog){ - if (!isSmartErrorLogCapable(smartval)) + if (!isSmartErrorLogCapable(smartval)){ printf("Device does not support Self Test Logging\n"); + returnval|=FAILSMART; + } else { - if(ataReadSelfTestLog(fd, &smartselftest)) + if(ataReadSelfTestLog(fd, &smartselftest)){ printf("Smartctl: SMART Self Test Log Read Failed\n"); + returnval|=FAILSMART; + } else ataPrintSmartSelfTestlog(smartselftest); } @@ -992,24 +1018,23 @@ void ataPrintMain (int fd){ // START OF THE TESTING SECTION OF THE CODE. IF NO TESTING, RETURN if (testcase==-1) - return; + return returnval; printf("\n=== START OF OFFLINE IMMEDIATE AND SELF-TEST SECTION ===\n"); - // if doing a self-test, be sure it's supported by the hardware if (testcase==OFFLINE_FULL_SCAN && !isSupportExecuteOfflineImmediate(smartval)){ printf("ERROR: device does not support Execute Off-Line Immediate function.\n\n"); - exit(-1); + return returnval|=FAILSMART; } else if (!isSupportSelfTest(smartval)){ printf ("ERROR: device does not support Self-Test functions.\n\n"); - exit(-1); + return returnval|=FAILSMART; } // Now do the test if (ataSmartTest(fd, testcase)) - exit(-1); + return returnval|=FAILSMART; // Tell user how long test will take to complete if ((timewait=TestTime(smartval,testcase))){ @@ -1019,5 +1044,5 @@ void ataPrintMain (int fd){ if (testcase!=SHORT_CAPTIVE_SELF_TEST && testcase!=EXTEND_CAPTIVE_SELF_TEST) printf ("Use smartctl -%c to abort test.\n", SMARTSELFTESTABORT); } - return; + return returnval; } diff --git a/sm5/ataprint.h b/sm5/ataprint.h index f76076f8c2c94b9312ee69bad6583c454e934cbe..09cfaa87b9cc95845eefbc2d215aecf2f8cdd085 100644 --- a/sm5/ataprint.h +++ b/sm5/ataprint.h @@ -26,7 +26,7 @@ #define _SMART_PRINT_H_ #ifndef CVSID2 -#define CVSID2 "$Id: ataprint.h,v 1.8 2002/10/22 11:40:52 ballen4705 Exp $\n" +#define CVSID2 "$Id: ataprint.h,v 1.9 2002/10/22 16:49:16 ballen4705 Exp $\n" #endif #include <stdio.h> @@ -58,6 +58,6 @@ void ataPseudoCheckSmart (struct ata_smart_values , /* prints 20 character string */ void ataPrintSmartAttribName (unsigned char id); -void ataPrintMain ( int fd ); +int ataPrintMain ( int fd ); #endif diff --git a/sm5/smartctl.8 b/sm5/smartctl.8 index 51bdca369e3d4af7e35d3bfd98fcf75cba1158c2..a5659bae192eb4bd8ded8256c9f50620f3f12cba 100644 --- a/sm5/smartctl.8 +++ b/sm5/smartctl.8 @@ -1,6 +1,6 @@ \# Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net> \# -\# $Id: smartctl.8,v 1.13 2002/10/22 12:53:20 ballen4705 Exp $ +\# $Id: smartctl.8,v 1.14 2002/10/22 16:49:16 ballen4705 Exp $ \# \# 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 the Free @@ -15,7 +15,7 @@ \# at the Concurrent Systems Laboratory (now part of the Storage Systems \# Research Center), Jack Baskin School of Engineering, University of \# California, Santa Cruz. http://ssrc.soe.ucsc.edu/ -.TH SMARTCTL 8 "$Date: 2002/10/22 12:53:20 $" "smartmontools-5.0" +.TH SMARTCTL 8 "$Date: 2002/10/22 16:49:16 $" "smartmontools-5.0" .SH NAME smartctl \- S.M.A.R.T. control utility .SH SYNOPSIS @@ -315,6 +315,18 @@ the S.M.A.R.T. error log., which can be seen with the '\-l' option. shows the vendor attributes, when the disk stores its power-on time internally in minutes rather than hours. +.PP +.SH RETURN VALUES + +The return values of smartctl are defined by a bitmask. For the +moment this only works on ATA disks. The different bits in the return +value are as follows. Bit 0: Command line did not parse. Bit 1: +Device open failed. Bit 2: SMART command to disk failed. Bit 3: +SMART status check returned "DISK FAILING". Bit 4: SMART status check +returned "DISK OK" but we found prefail attributes <= threshold. Bit +5: SMART status check returned "DISK OK" but we found that some (usage +or prefail) attributes have been <= threshold at some time in the +past. Bit 6: Unable to get Device IDENTITY information. .PP .SH AUTHOR Bruce Allen @@ -389,4 +401,4 @@ Please let us know if there is an on\-line source for this document. .SH CVS ID OF THIS PAGE: -$Id: smartctl.8,v 1.13 2002/10/22 12:53:20 ballen4705 Exp $ +$Id: smartctl.8,v 1.14 2002/10/22 16:49:16 ballen4705 Exp $ diff --git a/sm5/smartctl.c b/sm5/smartctl.c index 9652f404261a0927bfb8155ce053e2f48bab1c77..3e17e69704e931e95d9569940565756eb75b3ab9 100644 --- a/sm5/smartctl.c +++ b/sm5/smartctl.c @@ -37,7 +37,7 @@ #include "scsiprint.h" extern const char *CVSid1, *CVSid2, *CVSid4, *CVSid5; -const char* CVSid6="$Id: smartctl.c,v 1.13 2002/10/22 09:50:54 ballen4705 Exp $\n" +const char* CVSid6="$Id: smartctl.c,v 1.14 2002/10/22 16:49:16 ballen4705 Exp $\n" "\t" CVSID1 "\t" CVSID2 "\t" CVSID4 "\t" CVSID5 "\t" CVSID6 ; unsigned char driveinfo = FALSE; @@ -201,7 +201,7 @@ void ParseOpts (int argc, char** argv){ break; default: Usage(); - exit (-1); + exit(FAILCMD); } if ( (smartexeoffimmediate + smartshortselftest + @@ -209,7 +209,7 @@ void ParseOpts (int argc, char** argv){ smartextendcapselftest +smartselftestabort ) > 1){ Usage(); printf ("\nERROR: smartctl can only run a single test (or abort) at a time.\n\n"); - exit(-1); + exit(FAILCMD); } } } @@ -217,14 +217,14 @@ void ParseOpts (int argc, char** argv){ /* Main Program */ int main (int argc, char **argv){ - int fd; + int fd,retval=0; char *device; printf("smartctl version %d.%d-%d Copyright (C) 2002 Bruce Allen\n",RELEASE_MAJOR,RELEASE_MINOR,SMARTMONTOOLS_VERSION); printf("Home page of smartctl is %s\n",PROJECTHOME); // Part input arguments - ParseOpts (argc,argv); + ParseOpts(argc,argv); // Print Copyright/License info if needed if (printcopyleft){ @@ -234,29 +234,31 @@ int main (int argc, char **argv){ printf("See http://www.gnu.org for further details.\n\n"); printf("CVS version IDs of files used to build this code are:\n%s%s%s%s%s",CVSid1,CVSid2,CVSid4,CVSid5,CVSid6); if (argc==2) - exit(0); - } - + return 0; + } + // Further argument checking - if ( argc != 3 ){ + if (argc != 3){ Usage(); - exit (-1); + return FAILCMD; } - + // open device - read-only mode is enough to issue needed commands - fd = open ( device=argv[2], O_RDONLY ); + fd = open(device=argv[2], O_RDONLY); - if ( fd < 0) { - perror ( "Device open failed"); - exit(-1); + if (fd< 0) { + perror ("Smartctl device open failed:"); + return FAILDEV; } - if ( device[5] == 'h') - ataPrintMain (fd ); + if (device[5] == 'h') + retval=ataPrintMain(fd ); else if (device[5] == 's') scsiPrintMain (fd); - else + else { Usage(); - - return 0; + return FAILCMD; + } + + return retval; } diff --git a/sm5/smartctl.cpp b/sm5/smartctl.cpp index f57b2fba35e1f4b99cd7b79722c6c0d2b6bc28c3..467badd2bea195ed5d13593967522b62e65974d3 100644 --- a/sm5/smartctl.cpp +++ b/sm5/smartctl.cpp @@ -37,7 +37,7 @@ #include "scsiprint.h" extern const char *CVSid1, *CVSid2, *CVSid4, *CVSid5; -const char* CVSid6="$Id: smartctl.cpp,v 1.13 2002/10/22 09:50:54 ballen4705 Exp $\n" +const char* CVSid6="$Id: smartctl.cpp,v 1.14 2002/10/22 16:49:16 ballen4705 Exp $\n" "\t" CVSID1 "\t" CVSID2 "\t" CVSID4 "\t" CVSID5 "\t" CVSID6 ; unsigned char driveinfo = FALSE; @@ -201,7 +201,7 @@ void ParseOpts (int argc, char** argv){ break; default: Usage(); - exit (-1); + exit(FAILCMD); } if ( (smartexeoffimmediate + smartshortselftest + @@ -209,7 +209,7 @@ void ParseOpts (int argc, char** argv){ smartextendcapselftest +smartselftestabort ) > 1){ Usage(); printf ("\nERROR: smartctl can only run a single test (or abort) at a time.\n\n"); - exit(-1); + exit(FAILCMD); } } } @@ -217,14 +217,14 @@ void ParseOpts (int argc, char** argv){ /* Main Program */ int main (int argc, char **argv){ - int fd; + int fd,retval=0; char *device; printf("smartctl version %d.%d-%d Copyright (C) 2002 Bruce Allen\n",RELEASE_MAJOR,RELEASE_MINOR,SMARTMONTOOLS_VERSION); printf("Home page of smartctl is %s\n",PROJECTHOME); // Part input arguments - ParseOpts (argc,argv); + ParseOpts(argc,argv); // Print Copyright/License info if needed if (printcopyleft){ @@ -234,29 +234,31 @@ int main (int argc, char **argv){ printf("See http://www.gnu.org for further details.\n\n"); printf("CVS version IDs of files used to build this code are:\n%s%s%s%s%s",CVSid1,CVSid2,CVSid4,CVSid5,CVSid6); if (argc==2) - exit(0); - } - + return 0; + } + // Further argument checking - if ( argc != 3 ){ + if (argc != 3){ Usage(); - exit (-1); + return FAILCMD; } - + // open device - read-only mode is enough to issue needed commands - fd = open ( device=argv[2], O_RDONLY ); + fd = open(device=argv[2], O_RDONLY); - if ( fd < 0) { - perror ( "Device open failed"); - exit(-1); + if (fd< 0) { + perror ("Smartctl device open failed:"); + return FAILDEV; } - if ( device[5] == 'h') - ataPrintMain (fd ); + if (device[5] == 'h') + retval=ataPrintMain(fd ); else if (device[5] == 's') scsiPrintMain (fd); - else + else { Usage(); - - return 0; + return FAILCMD; + } + + return retval; } diff --git a/sm5/smartctl.h b/sm5/smartctl.h index d8ec2f2b2689a08648b0d263729c8117754c8a19..41d7ead978cdb634051888565a2650183476d52a 100644 --- a/sm5/smartctl.h +++ b/sm5/smartctl.h @@ -26,7 +26,7 @@ #define __SMARTCTL_H_ #ifndef CVSID6 -#define CVSID6 "$Id: smartctl.h,v 1.7 2002/10/22 09:44:55 ballen4705 Exp $\n" +#define CVSID6 "$Id: smartctl.h,v 1.8 2002/10/22 16:49:16 ballen4705 Exp $\n" #endif /* Defines for command line options */ @@ -57,4 +57,28 @@ #define TRUE 0x01 #define FALSE 0x00 +// Return codes (bitmask) + +// command line did not parse +#define FAILCMD (0x01<<0) + +// device open failed +#define FAILDEV (0x01<<1) + +// smart command failed +#define FAILSMART (0x01<<2) + +// SMART STATUS returned FAILURE +#define FAILSTATUS (0x01<<3) + +// Attributes found <= threshold with prefail=1 +#define FAILATTR (0x01<<4) + +// SMART STATUS returned GOOD but age attributes failed or prefail +// attributes have failed in the past +#define FAILAGE (0x01<<5) + +// Device ID failed +#define FAILID (0x01<<6) + #endif