diff --git a/check_smart/check_smart.cpp b/check_smart/check_smart.cpp index 985f66a..dcab69d 100644 --- a/check_smart/check_smart.cpp +++ b/check_smart/check_smart.cpp @@ -2,76 +2,80 @@ const char *servicename = (const char*)"SMART"; -int getSmartAttrValue(string line) -{ +int getSmartAttrValue(string line) { return stoi(line.substr(line.find_last_of(" ")+1)); } -int getSmartAttrID(string line) -{ +int getSmartAttrID(string line) { size_t first = line.find_first_not_of(' '); size_t last = line.find_first_of(' ',first); int id = -1; - try {id = stoi(line.substr(first,last-first));} - catch(...){} + try { + id = stoi(line.substr(first,last-first)); + } + catch(...){ + return -1; + } return id; } -int checkDriveType(const char* disk) -{ +int checkDriveType(const char* disk) { string output = ""; string RRLine = ""; string line= ""; int rc = run_smartctl_cmd(string(SMARTCTL_CMD_INFO), disk,&output); - if(rc) - { + if(rc) { cout << "Error reading SMART data from disk " << disk << endl; exit(3); } stringstream sstream; sstream.str(output); - while(getline(sstream,line) && RRLine == "") - { + while(getline(sstream,line) && RRLine == "") { size_t found = line.find(ROTATION_INFO_STR); - if(found != string::npos) {RRLine = line;} + if(found != string::npos) { + RRLine = line; + } } - if(RRLine != "") - { + if(RRLine != "") { size_t found = RRLine.find(SSD_DEV_STR); - if(found != string::npos) {return SSD;} + if(found != string::npos) { + return SSD; + } } return HDD; } -map prepareAttrMap(int driveType) -{ +map prepareAttrMap(int driveType) { map map; SMARTAttr realloc; realloc.name = "Reallocated_Sector_Ct"; realloc.value = -1; realloc.severity = WARN; + realloc.optional = false; map[REALLOC_SEC_COUNT_ID] = realloc; SMARTAttr pending; SMARTAttr off_uncorrect; SMARTAttr wear; + SMARTAttr wearout; SMARTAttr badblocks; SMARTAttr rep_uncorrect; - switch(driveType) - { + switch(driveType) { case HDD: pending.name = "Current_Pending_Sector"; pending.value = -1; pending.severity = CRIT; + pending.optional = false; map[CURRENT_PENDING_SEC_ID] = pending; off_uncorrect.name = "Offline_Uncorrectable"; off_uncorrect.value = -1; off_uncorrect.severity = CRIT; + off_uncorrect.optional = false; map[OFFLINE_UNCORRECT_ID] = off_uncorrect; break; @@ -79,16 +83,25 @@ map prepareAttrMap(int driveType) wear.name = "Wear_Leveling_Count"; wear.value = -1; wear.severity = WARN; + wear.optional = true; map[WEAR_COUNT_ID] = wear; + wearout.name = "Media_Wearout_Indicator"; + wearout.value = -1; + wearout.severity = WARN; + wearout.optional = true; + map[WEAR_COUNT_ID] = wearout; + badblocks.name = "Runtime_Bad_Block"; badblocks.value = -1; badblocks.severity = CRIT; + badblocks.optional = false; map[RUNTIME_BAD_BLOCKS_IDD] = badblocks; rep_uncorrect.name = "Reported_Uncorrect"; rep_uncorrect.value = -1; rep_uncorrect.severity = CRIT; + rep_uncorrect.optional = false; map[REP_UNCORRECT_ID] = rep_uncorrect; break; @@ -96,14 +109,12 @@ map prepareAttrMap(int driveType) return map; } -int evalStatus(const char* disk, int driveType, string *status) -{ +int evalStatus(const char* disk, int driveType, string *status) { string output = ""; string line = ""; int rc = run_smartctl_cmd(string(SMARTCTL_CMD_ATTRS), disk,&output); - if(rc) - { + if(rc) { cout << "Error reading SMART data from disk " << disk << endl; exit(UNKN); } @@ -112,34 +123,42 @@ int evalStatus(const char* disk, int driveType, string *status) stringstream sstream; sstream.str(output); - while(getline(sstream,line)) - { - for(map::iterator it = attrMap.begin(); it != attrMap.end(); ++it) - { + while(getline(sstream,line)) { + for(map::iterator it = attrMap.begin(); it != attrMap.end(); ++it) { int id = it->first; - if(getSmartAttrID(line) == id) {attrMap[id].value = getSmartAttrValue(line);} + int attrID = getSmartAttrID(line); + if(attrID == -1) { + continue; + } + if(getSmartAttrID(line) == id) { + attrMap[id].value = getSmartAttrValue(line); + } } } int ret = OK; *status = string(disk); - for(map::iterator it = attrMap.begin(); it != attrMap.end(); ++it) - { + for(map::iterator it = attrMap.begin(); it != attrMap.end(); ++it) { int id = it->first; SMARTAttr attr = it->second; - if(attr.value == -1) - { + if(attr.value == -1) { + if(attr.optional) { + continue; + } *status = string(disk) + " status UNKNOWN"; return UNKN; } int veredict = 0; - if(attr.value) {veredict = attr.severity;} - switch(veredict) - { + if(attr.value) { + veredict = attr.severity; + } + switch(veredict) { case OK: break; case WARN: - if(ret == OK) {ret = WARN;} + if(ret == OK) { + ret = WARN; + } break; case CRIT: ret = CRIT; @@ -150,8 +169,7 @@ int evalStatus(const char* disk, int driveType, string *status) return ret; } -int run_smartctl_cmd(const string command, const char* disk, string* output) -{ +int run_smartctl_cmd(const string command, const char* disk, string* output) { int uid = getuid(); setreuid(0,0); @@ -161,15 +179,12 @@ int run_smartctl_cmd(const string command, const char* disk, string* output) return rc; } -void printVersion() -{ +void printVersion() { cout << "check_smart v" << VERSION << endl << endl; } -void printHelp(bool longVersion) -{ - if(longVersion) - { +void printHelp(bool longVersion) { + if(longVersion) { printVersion(); cout << "Checks for pending, reallocated or uncorrectable sectors in disks using SMART" << endl << "WARNING: Requires the setuid bit to be set to run as root" << endl << endl; printHelp(false); @@ -185,8 +200,7 @@ void printHelp(bool longVersion) cout << "Usage: " << endl << "check_smart [-hV] DISKS..." << endl << endl; } -void set_timeout(unsigned int sec) -{ +void set_timeout(unsigned int sec) { struct itimerval timer; timer.it_value.tv_sec = sec; timer.it_value.tv_usec = 0; @@ -200,14 +214,11 @@ void set_timeout(unsigned int sec) sigaction (SIGVTALRM, &sa, 0); } -int main(int argc, char **argv) -{ +int main(int argc, char **argv) { set_timeout(10); int c; - while ((c = getopt (argc, argv, "Vh")) != -1) - { - switch(c) - { + while ((c = getopt (argc, argv, "Vh")) != -1) { + switch(c) { case 'h': printHelp(true); return OK; @@ -220,8 +231,7 @@ int main(int argc, char **argv) } } - if(argc == 1) - { + if(argc == 1) { cout << "No disks checked" << endl; return 3; } @@ -229,11 +239,9 @@ int main(int argc, char **argv) string *results = new string[argc-1]; int returnCode = OK; - for(int i = 1; i < argc; i++) - { + for(int i = 1; i < argc; i++) { int driveType = checkDriveType(argv[i]); - switch(driveType) - { + switch(driveType) { case HDD: case SSD: break; @@ -243,8 +251,7 @@ int main(int argc, char **argv) break; } - switch(evalStatus(argv[i],driveType,&(results[i-1]))) - { + switch(evalStatus(argv[i],driveType,&(results[i-1]))) { case OK: break; case WARN: @@ -253,6 +260,9 @@ int main(int argc, char **argv) case CRIT: returnCode = CRIT; break; + case UNKN: + returnCode = UNKN; + break; } } @@ -261,8 +271,7 @@ int main(int argc, char **argv) else if(returnCode == WARN) {cout << " WARNING - disk status: ";} else if(returnCode == CRIT) {cout << " CRITICAL - disk status: ";} else if(returnCode == UNKN) {cout << " UNKNOWN - disk status: ";} - for(int i = 0; i < (argc-1); i++) - { + for(int i = 0; i < (argc-1); i++) { cout << results[i]; if(i != (argc-2)) {cout << ", ";} } diff --git a/check_smart/check_smart.h b/check_smart/check_smart.h index 877cce3..ac61fe7 100755 --- a/check_smart/check_smart.h +++ b/check_smart/check_smart.h @@ -31,6 +31,7 @@ #define CURRENT_PENDING_SEC_ID 197 #define OFFLINE_UNCORRECT_ID 198 #define WEAR_COUNT_ID 177 +#define MEDIA_WEAROUT_INDICATOR 233 #define RUNTIME_BAD_BLOCKS_IDD 183 #define REP_UNCORRECT_ID 187 @@ -44,6 +45,7 @@ struct SMARTAttr string name; int value; int severity; + bool optional; }; typedef struct SMARTAttr SMARTAttr;