From ec5ba94a18b729f43bdd617938d946ae942bd7e7 Mon Sep 17 00:00:00 2001
From: ballen4705 <ballen4705@4ea69e1a-61f1-4043-bf83-b5c94c648137>
Date: Tue, 22 Oct 2002 11:40:52 +0000
Subject: [PATCH] Modified -v option. Now prints additional fields for vendor
 attributes. One field says if attribute is currently failing or has ever
 failed.  Other field says if it is a pre-failure or usage/old-age attribute.

git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@80 4ea69e1a-61f1-4043-bf83-b5c94c648137
---
 sm5/CHANGELOG    |   8 ++-
 sm5/ataprint.c   | 145 +++++++++++++++++++++++++++++------------------
 sm5/ataprint.cpp | 145 +++++++++++++++++++++++++++++------------------
 sm5/ataprint.h   |   5 +-
 4 files changed, 190 insertions(+), 113 deletions(-)

diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG
index c761d668a..834f014f3 100644
--- a/sm5/CHANGELOG
+++ b/sm5/CHANGELOG
@@ -1,6 +1,6 @@
 CHANGELOG for smartmontools
 
-$Id: CHANGELOG,v 1.12 2002/10/21 16:00:46 ballen4705 Exp $
+$Id: CHANGELOG,v 1.13 2002/10/22 11:40:52 ballen4705 Exp $
 
 Copyright (C) 2002 Bruce Allen <smartmontools-support@lists.sourceforge.net>
 
@@ -29,6 +29,12 @@ NOTES FOR NEXT RELEASE:
 
 smartmontools-5.0-11
 
+    Modified function that prints vendor attributes to say if the
+    attribute has currently failed or has ever failed.
+
+    -p option now prints out license info and CVS strings for all
+    modules in the code.
+
     Previous versions of this code (and Smartsuite) only generate
     SMART failure errors if the value of an attribute is below the
     threshold and the prefailure bit is set.  However the ATA Spec
diff --git a/sm5/ataprint.c b/sm5/ataprint.c
index e59f58dbe..2a2d6680f 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.17 2002/10/22 09:56:38 ballen4705 Exp $\n"
+const char *CVSid4="$Id: ataprint.c,v 1.18 2002/10/22 11:40:52 ballen4705 Exp $\n"
 	           "\t" CVSID2 "\t" CVSID3 "\t" CVSID6 ;
 
 // Function for printing ASCII byte-swapped strings, skipping white
@@ -357,61 +357,96 @@ void PrintSmartExtendedSelfTestPollingTime ( struct ata_smart_values data)
 }
 
 
+// onlyfailing is a bitflag
+// onlyfailing=0 : all values
+// onlyfailing=1:  just ones that are currently failed and have prefailure bit set
+// onlyfailing=2:  ones that are failed, or have failed with or without prefailure bit set
+void PrintSmartAttribWithThres (struct ata_smart_values data, 
+				struct ata_smart_thresholds thresholds,
+				int onlyfailed){
+  int i,j;
+  long long rawvalue;
+  int needheader=1;
+    
+  // step through all vendor attributes
+  for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){
+    char *status;
+    struct ata_smart_attribute *disk=data.vendor_attributes+i;
+    struct ata_smart_threshold_entry *thre=thresholds.thres_entries+i;
+    
+    // consider only valid attributes
+    if (disk->id && thre->id){
+      char *type;
+      int failednow,failedever;
 
-void PrintSmartAttribWithThres ( struct ata_smart_values data, 
-                                 struct ata_smart_thresholds thresholds)
-{
-   int i,j;
-   long long rawvalue; 
-   printf ("Vendor Specific SMART Attributes with Thresholds:\n");
-   printf ("Revision Number: %i\n", data.revnumber);
-   printf ("Attribute                    Flag     Value Worst Threshold Raw Value\n");
-	
-   for ( i = 0 ; i < NUMBER_ATA_SMART_ATTRIBUTES ; i++ ){
-     // step through all vendor attributes
-     if (data.vendor_attributes[i].id && thresholds.thres_entries[i].id){
-       ataPrintSmartAttribName(data.vendor_attributes[i].id);
-       // printing if they contain something sensible
-       printf(" 0x%04x   %.3i   %.3i   %.3i       ", 
-	      data.vendor_attributes[i].status.all,
-	      data.vendor_attributes[i].current,
-	      data.vendor_attributes[i].worst,
-	      thresholds.thres_entries[i].threshold);
-
-       // convert the six individual bytes to a long long (8 byte) integer
-       rawvalue = 0;
-       for (j = 0 ; j < 6 ; j++)
-	 rawvalue |= data.vendor_attributes[i].raw[j] << (8*j) ;
-
-       // This switch statement is where we handle Raw attributes
-       // that are stored in an unusual vendor-specific format,
-       switch (data.vendor_attributes[i].id){
-
-	 // Power on time
-       case 9:
-	 if (smart009minutes)
-	   // minutes
-	   printf ("%llu h + %2llu m\n",rawvalue/60,rawvalue%60);
-	 else
+      failednow =disk->current <= thre->threshold;
+      failedever=disk->worst   <= thre->threshold;
+      
+      // These break out of the loop if we are only printing certain entries...
+      if (onlyfailed==1 && (!disk->status.flag.prefailure || !failednow))
+	break;
+      
+      if (onlyfailed==2 && !failedever)
+	break;
+      
+      // print header only if needed
+      if (needheader){
+	printf ("SMART Data Structure revision number: %i\n",data.revnumber);
+	printf ("Vendor Specific SMART Attributes with Thresholds:\n"
+		"Attribute                    Flag     Value Worst Threshold Type     Ever_Failed? Raw_Value\n");
+	needheader=0;
+      }
+      
+      // is this currently failed, or has it ever failed?
+      if (failednow)
+	status="FAILED NOW";
+      else if (failedever)
+	status="In the past";
+      else
+	status="    -";
+      
+      // Print name of attribute
+      ataPrintSmartAttribName(disk->id);
+      
+      // printing line for each valid attribute
+      type=disk->status.flag.prefailure?"Pre-fail":"Old age";
+      printf(" 0x%04x   %.3i   %.3i   %.3i       %-9s%-13s", 
+	     disk->status.all, disk->current, disk->worst,
+	     thre->threshold, type, status);
+      
+      // convert the six individual bytes to a long long (8 byte) integer
+      rawvalue = 0;
+      for (j = 0 ; j < 6 ; j++)
+	rawvalue |= disk->raw[j] << (8*j) ;
+      
+      // This switch statement is where we handle Raw attributes
+      // that are stored in an unusual vendor-specific format,
+      switch (disk->id){
+	// Power on time
+      case 9:
+	if (smart009minutes)
+	  // minutes
+	  printf ("%llu h + %2llu m\n",rawvalue/60,rawvalue%60);
+	else
 	   // hours
-	   printf ("%llu\n", rawvalue);  //stored in hours
-	 break;
-	 
-	 // Temperature
-       case 194:
-	 printf ("%u", data.vendor_attributes[i].raw[0]);
-	 if (rawvalue==data.vendor_attributes[i].raw[0])
-	   printf("\n");
-	 else
-	   // The other bytes are in use. Try IBM's model
-	   printf(" (Lifetime Min/Max %u/%u)\n",data.vendor_attributes[i].raw[2],
-		  data.vendor_attributes[i].raw[4]);
-	 break;
-       default:
-	 printf("%llu\n", rawvalue);
-       }	    
-     }
-   }
+	  printf ("%llu\n", rawvalue);  //stored in hours
+	break;
+	
+	// Temperature
+      case 194:
+	printf ("%u", disk->raw[0]);
+	if (rawvalue==disk->raw[0])
+	  printf("\n");
+	else
+	  // The other bytes are in use. Try IBM's model
+	  printf(" (Lifetime Min/Max %u/%u)\n",disk->raw[2],
+		 disk->raw[4]);
+	break;
+      default:
+	printf("%llu\n", rawvalue);
+      }	    
+    }
+  }
 }
 
 
@@ -907,7 +942,7 @@ void ataPrintMain (int fd){
   
   // Print vendor-specific attributes
   if (smartvendorattrib)
-    PrintSmartAttribWithThres(smartval, smartthres);
+    PrintSmartAttribWithThres(smartval, smartthres,0);
 	
   // Print SMART error log
   if (smarterrorlog){
diff --git a/sm5/ataprint.cpp b/sm5/ataprint.cpp
index e4e5992ef..a5db46835 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.17 2002/10/22 09:56:38 ballen4705 Exp $\n"
+const char *CVSid4="$Id: ataprint.cpp,v 1.18 2002/10/22 11:40:52 ballen4705 Exp $\n"
 	           "\t" CVSID2 "\t" CVSID3 "\t" CVSID6 ;
 
 // Function for printing ASCII byte-swapped strings, skipping white
@@ -357,61 +357,96 @@ void PrintSmartExtendedSelfTestPollingTime ( struct ata_smart_values data)
 }
 
 
+// onlyfailing is a bitflag
+// onlyfailing=0 : all values
+// onlyfailing=1:  just ones that are currently failed and have prefailure bit set
+// onlyfailing=2:  ones that are failed, or have failed with or without prefailure bit set
+void PrintSmartAttribWithThres (struct ata_smart_values data, 
+				struct ata_smart_thresholds thresholds,
+				int onlyfailed){
+  int i,j;
+  long long rawvalue;
+  int needheader=1;
+    
+  // step through all vendor attributes
+  for (i=0; i<NUMBER_ATA_SMART_ATTRIBUTES; i++){
+    char *status;
+    struct ata_smart_attribute *disk=data.vendor_attributes+i;
+    struct ata_smart_threshold_entry *thre=thresholds.thres_entries+i;
+    
+    // consider only valid attributes
+    if (disk->id && thre->id){
+      char *type;
+      int failednow,failedever;
 
-void PrintSmartAttribWithThres ( struct ata_smart_values data, 
-                                 struct ata_smart_thresholds thresholds)
-{
-   int i,j;
-   long long rawvalue; 
-   printf ("Vendor Specific SMART Attributes with Thresholds:\n");
-   printf ("Revision Number: %i\n", data.revnumber);
-   printf ("Attribute                    Flag     Value Worst Threshold Raw Value\n");
-	
-   for ( i = 0 ; i < NUMBER_ATA_SMART_ATTRIBUTES ; i++ ){
-     // step through all vendor attributes
-     if (data.vendor_attributes[i].id && thresholds.thres_entries[i].id){
-       ataPrintSmartAttribName(data.vendor_attributes[i].id);
-       // printing if they contain something sensible
-       printf(" 0x%04x   %.3i   %.3i   %.3i       ", 
-	      data.vendor_attributes[i].status.all,
-	      data.vendor_attributes[i].current,
-	      data.vendor_attributes[i].worst,
-	      thresholds.thres_entries[i].threshold);
-
-       // convert the six individual bytes to a long long (8 byte) integer
-       rawvalue = 0;
-       for (j = 0 ; j < 6 ; j++)
-	 rawvalue |= data.vendor_attributes[i].raw[j] << (8*j) ;
-
-       // This switch statement is where we handle Raw attributes
-       // that are stored in an unusual vendor-specific format,
-       switch (data.vendor_attributes[i].id){
-
-	 // Power on time
-       case 9:
-	 if (smart009minutes)
-	   // minutes
-	   printf ("%llu h + %2llu m\n",rawvalue/60,rawvalue%60);
-	 else
+      failednow =disk->current <= thre->threshold;
+      failedever=disk->worst   <= thre->threshold;
+      
+      // These break out of the loop if we are only printing certain entries...
+      if (onlyfailed==1 && (!disk->status.flag.prefailure || !failednow))
+	break;
+      
+      if (onlyfailed==2 && !failedever)
+	break;
+      
+      // print header only if needed
+      if (needheader){
+	printf ("SMART Data Structure revision number: %i\n",data.revnumber);
+	printf ("Vendor Specific SMART Attributes with Thresholds:\n"
+		"Attribute                    Flag     Value Worst Threshold Type     Ever_Failed? Raw_Value\n");
+	needheader=0;
+      }
+      
+      // is this currently failed, or has it ever failed?
+      if (failednow)
+	status="FAILED NOW";
+      else if (failedever)
+	status="In the past";
+      else
+	status="    -";
+      
+      // Print name of attribute
+      ataPrintSmartAttribName(disk->id);
+      
+      // printing line for each valid attribute
+      type=disk->status.flag.prefailure?"Pre-fail":"Old age";
+      printf(" 0x%04x   %.3i   %.3i   %.3i       %-9s%-13s", 
+	     disk->status.all, disk->current, disk->worst,
+	     thre->threshold, type, status);
+      
+      // convert the six individual bytes to a long long (8 byte) integer
+      rawvalue = 0;
+      for (j = 0 ; j < 6 ; j++)
+	rawvalue |= disk->raw[j] << (8*j) ;
+      
+      // This switch statement is where we handle Raw attributes
+      // that are stored in an unusual vendor-specific format,
+      switch (disk->id){
+	// Power on time
+      case 9:
+	if (smart009minutes)
+	  // minutes
+	  printf ("%llu h + %2llu m\n",rawvalue/60,rawvalue%60);
+	else
 	   // hours
-	   printf ("%llu\n", rawvalue);  //stored in hours
-	 break;
-	 
-	 // Temperature
-       case 194:
-	 printf ("%u", data.vendor_attributes[i].raw[0]);
-	 if (rawvalue==data.vendor_attributes[i].raw[0])
-	   printf("\n");
-	 else
-	   // The other bytes are in use. Try IBM's model
-	   printf(" (Lifetime Min/Max %u/%u)\n",data.vendor_attributes[i].raw[2],
-		  data.vendor_attributes[i].raw[4]);
-	 break;
-       default:
-	 printf("%llu\n", rawvalue);
-       }	    
-     }
-   }
+	  printf ("%llu\n", rawvalue);  //stored in hours
+	break;
+	
+	// Temperature
+      case 194:
+	printf ("%u", disk->raw[0]);
+	if (rawvalue==disk->raw[0])
+	  printf("\n");
+	else
+	  // The other bytes are in use. Try IBM's model
+	  printf(" (Lifetime Min/Max %u/%u)\n",disk->raw[2],
+		 disk->raw[4]);
+	break;
+      default:
+	printf("%llu\n", rawvalue);
+      }	    
+    }
+  }
 }
 
 
@@ -907,7 +942,7 @@ void ataPrintMain (int fd){
   
   // Print vendor-specific attributes
   if (smartvendorattrib)
-    PrintSmartAttribWithThres(smartval, smartthres);
+    PrintSmartAttribWithThres(smartval, smartthres,0);
 	
   // Print SMART error log
   if (smarterrorlog){
diff --git a/sm5/ataprint.h b/sm5/ataprint.h
index 6564e8973..f76076f8c 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.7 2002/10/22 09:44:55 ballen4705 Exp $\n"
+#define CVSID2 "$Id: ataprint.h,v 1.8 2002/10/22 11:40:52 ballen4705 Exp $\n"
 #endif
 
 #include <stdio.h>
@@ -46,7 +46,8 @@ void ataPrintSmartErrorlog (struct ata_smart_errorlog);
 void PrintSmartAttributes (struct ata_smart_values data);
 
 void PrintSmartAttribWithThres (struct ata_smart_values data,
-                                struct ata_smart_thresholds thresholds);
+                                struct ata_smart_thresholds thresholds,
+				int onlyfailed);
 
 void ataPrintSmartSelfTestlog (struct ata_smart_selftestlog data);
 
-- 
GitLab