From 9e19366acf617fbe31392ced17a1f2d457c21cda Mon Sep 17 00:00:00 2001
From: chrfranke <chrfranke@4ea69e1a-61f1-4043-bf83-b5c94c648137>
Date: Sat, 13 Jun 2009 14:56:20 +0000
Subject: [PATCH] Print General Purpose Logs even if GPL feature bit is
 missing. Change order of the extended log outputs.

git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@2800 4ea69e1a-61f1-4043-bf83-b5c94c648137
---
 sm5/CHANGELOG    |   9 +-
 sm5/ataprint.cpp | 271 ++++++++++++++++++++++-------------------------
 2 files changed, 137 insertions(+), 143 deletions(-)

diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG
index a22e54df1..8c3a1dad8 100644
--- a/sm5/CHANGELOG
+++ b/sm5/CHANGELOG
@@ -1,6 +1,6 @@
 CHANGELOG for smartmontools
 
-$Id: CHANGELOG,v 1.803 2009/06/12 12:25:02 chrfranke Exp $
+$Id: CHANGELOG,v 1.804 2009/06/13 14:56:20 chrfranke Exp $
 
 The most recent version of this file is:
 http://smartmontools.cvs.sourceforge.net/smartmontools/sm5/CHANGELOG?view=markup
@@ -41,6 +41,13 @@ NOTES FOR FUTURE RELEASES: see TODO file.
 
 <DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE>
 
+  [CF] Print General Purpose Logs even if GPL feature bit is missing.
+       Needed for some older disks which implement READ LOG EXT but
+       do not report the GPL feature set.
+       Change order of the extended log outputs ('-l xerror',
+       '-l xselftest', '-l sataphy'). Extended logs are now printed
+       before their old versions.
+
   [CF] autogen.sh: automake 1.10.2 and 1.11 are OK.
 
   [CF] Fix syntax error in prototype of 'safe_snprintf()'.
diff --git a/sm5/ataprint.cpp b/sm5/ataprint.cpp
index f9182fa5f..78faf9d9a 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.210 2009/04/16 21:24:08 chrfranke Exp $"
+const char *ataprint_c_cvsid="$Id: ataprint.cpp,v 1.211 2009/06/13 14:56:20 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
@@ -2040,165 +2040,125 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
   }
 
   // Print SMART and/or GP log Directory and/or logs
+  // Get #pages for extended SMART logs
+  ata_smart_log_directory smartlogdir_buf, gplogdir_buf;
+  const ata_smart_log_directory * smartlogdir = 0, * gplogdir = 0;
+
   if (   options.gp_logdir || options.smart_logdir
       || options.sataphy || options.smart_ext_error_log
       || options.smart_ext_selftest_log
       || !options.log_requests.empty()                 ) {
-
-    bool gpl_cap = !!isGeneralPurposeLoggingCapable(&drive);
-    bool gpl_try = gpl_cap;
-    if (!gpl_try && con->permissive) {
-        con->permissive--;
-        gpl_try = true;
+    PRINT_ON(con);
+    if (isGeneralPurposeLoggingCapable(&drive))
+      pout("General Purpose Logging (GPL) feature set supported\n");
+
+    // Detect directories needed
+    bool need_smart_logdir = options.smart_logdir;
+    bool need_gp_logdir    = (   options.gp_logdir
+                              || options.smart_ext_error_log
+                              || options.smart_ext_selftest_log);
+    unsigned i;
+    for (i = 0; i < options.log_requests.size(); i++) {
+      if (options.log_requests[i].gpl)
+        need_gp_logdir = true;
+      else
+        need_smart_logdir = true;
     }
 
-    if (!gpl_try) {
-      pout("Device does not support General Purpose Loggin (GPL) feature set\n"
-           "(override with '-T permissive' option)\n");
-      failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
-    }
-    else {
-      PRINT_ON(con);
-      if (gpl_cap)
-        pout("General Purpose Logging (GPL) feature set supported\n");
-
-      // Detect directories needed
-      bool need_smart_logdir = options.smart_logdir;
-      bool need_gp_logdir    = (    options.gp_logdir
-                                || options.smart_ext_error_log
-                                || options.smart_ext_selftest_log);
-      unsigned i;
-      for (i = 0; i < options.log_requests.size(); i++) {
-        if (options.log_requests[i].gpl)
-          need_gp_logdir = true;
-        else
-          need_smart_logdir = true;
-      }
-
-      ata_smart_log_directory smartlogdir_buf, gplogdir_buf;
-      const ata_smart_log_directory * smartlogdir = 0, * gplogdir = 0;
-
-      // Read SMART Log directory
-      if (need_smart_logdir) {
-        if (ataReadLogDirectory(device, &smartlogdir_buf, false)){
-          PRINT_OFF(con);
-          pout("Read SMART Log Directory failed.\n\n");
-          failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
-        }
-        else
-          smartlogdir = &smartlogdir_buf;
+    // Read SMART Log directory
+    if (need_smart_logdir) {
+      if (ataReadLogDirectory(device, &smartlogdir_buf, false)){
+        PRINT_OFF(con);
+        pout("Read SMART Log Directory failed.\n\n");
+        failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
       }
-      PRINT_ON(con);
+      else
+        smartlogdir = &smartlogdir_buf;
+    }
+    PRINT_ON(con);
 
-      // Read GP Log directory
-      if (need_gp_logdir) {
-        if (ataReadLogDirectory(device, &gplogdir_buf, true)){
-          PRINT_OFF(con);
-          pout("Read GP Log Directory failed.\n\n");
-          failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
-        }
-        else
-          gplogdir = &gplogdir_buf;
+    // Read GP Log directory
+    if (need_gp_logdir) {
+      if (ataReadLogDirectory(device, &gplogdir_buf, true)){
+        PRINT_OFF(con);
+        pout("Read GP Log Directory failed.\n\n");
+        failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
       }
-      PRINT_ON(con);
+      else
+        gplogdir = &gplogdir_buf;
+    }
+    PRINT_ON(con);
 
-      // Print log directories
-      if ((options.gp_logdir && gplogdir) || (options.smart_logdir && smartlogdir))
-        PrintLogDirectories(gplogdir, smartlogdir);
-      PRINT_OFF(con);
+    // Print log directories
+    if ((options.gp_logdir && gplogdir) || (options.smart_logdir && smartlogdir))
+      PrintLogDirectories(gplogdir, smartlogdir);
+    PRINT_OFF(con);
 
-      // Print log pages
-      for (i = 0; i < options.log_requests.size(); i++) {
-        const ata_log_request & req = options.log_requests[i];
+    // Print log pages
+    for (i = 0; i < options.log_requests.size(); i++) {
+      const ata_log_request & req = options.log_requests[i];
 
-        const char * type;
-        unsigned max_nsectors;
-        if (req.gpl) {
-          type = "General Purpose";
-          max_nsectors = GetNumLogSectors(gplogdir, req.logaddr, true);
-        }
-        else {
-          type = "SMART";
-          max_nsectors = GetNumLogSectors(smartlogdir, req.logaddr, false);
-        }
+      const char * type;
+      unsigned max_nsectors;
+      if (req.gpl) {
+        type = "General Purpose";
+        max_nsectors = GetNumLogSectors(gplogdir, req.logaddr, true);
+      }
+      else {
+        type = "SMART";
+        max_nsectors = GetNumLogSectors(smartlogdir, req.logaddr, false);
+      }
 
-        if (!max_nsectors) {
-          if (!con->permissive) {
-            pout("%s Log 0x%02x does not exist (override with '-T permissive' option)\n", type, req.logaddr);
-            continue;
-          }
-          con->permissive--;
-          max_nsectors = req.page+1;
-        }
-        if (max_nsectors <= req.page) {
-          pout("%s Log 0x%02x has only %u sectors, output skipped\n", type, req.logaddr, max_nsectors);
+      if (!max_nsectors) {
+        if (!con->permissive) {
+          pout("%s Log 0x%02x does not exist (override with '-T permissive' option)\n", type, req.logaddr);
           continue;
         }
-
-        unsigned ns = req.nsectors;
-        if (ns > max_nsectors - req.page) {
-          if (req.nsectors != ~0U) // "FIRST-max"
-            pout("%s Log 0x%02x has only %u sectors, output truncated\n", type, req.logaddr, max_nsectors);
-          ns = max_nsectors - req.page;
-        }
-
-        // SMART log don't support sector offset, start with first sector
-        unsigned offs = (req.gpl ? 0 : req.page);
-
-        raw_buffer log_buf((offs + ns) * 512);
-        bool ok;
-        if (req.gpl)
-          ok = ataReadLogExt(device, req.logaddr, 0x00, req.page, log_buf.data(), ns);
-        else
-          ok = ataReadSmartLog(device, req.logaddr, log_buf.data(), offs + ns);
-        if (!ok)
-          failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
-        else
-          PrintLogPages(type, log_buf.data() + offs*512, req.logaddr, req.page, ns, max_nsectors);
+        con->permissive--;
+        max_nsectors = req.page+1;
       }
-
-      // Print SMART Extendend Comprehensive Error Log
-      if (options.smart_ext_error_log) {
-        unsigned nsectors = GetNumLogSectors(gplogdir, 0x03, true);
-        if (!nsectors)
-          pout("SMART Extended Comprehensive Error Log (GP Log 0x03) does not exist\n");
-        else if (nsectors >= 256)
-          pout("SMART Extended Comprehensive Error Log size %u not supported\n", nsectors);
-        else {
-          raw_buffer log_03_buf(nsectors * 512);
-          ata_smart_exterrlog * log_03 = (ata_smart_exterrlog *)log_03_buf.data();
-          if (!ataReadExtErrorLog(device, log_03, nsectors))
-            failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
-          else
-            PrintSmartExtErrorLog(log_03, nsectors, options.smart_ext_error_log);
-        }
+      if (max_nsectors <= req.page) {
+        pout("%s Log 0x%02x has only %u sectors, output skipped\n", type, req.logaddr, max_nsectors);
+        continue;
       }
 
-      // Print SMART Extendend Self-test Log
-      if (options.smart_ext_selftest_log) {
-        unsigned nsectors = GetNumLogSectors(gplogdir, 0x07, true);
-        if (!nsectors)
-          pout("SMART Extended Self-test Log (GP Log 0x07) does not exist\n");
-        else if (nsectors >= 256)
-          pout("SMART Extended Self-test Log size %u not supported\n", nsectors);
-        else {
-          raw_buffer log_07_buf(nsectors * 512);
-          ata_smart_extselftestlog * log_07 = (ata_smart_extselftestlog *)log_07_buf.data();
-          if (!ataReadExtSelfTestLog(device, log_07, nsectors))
-            failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
-          else
-            PrintSmartExtSelfTestLog(log_07, nsectors, options.smart_ext_selftest_log);
-        }
-      }
-      // Print SATA Phy Event Counters
-      if (options.sataphy) {
-        unsigned char log_11[512] = {0, };
-        unsigned char features = (options.sataphy_reset ? 0x01 : 0x00);
-        if (!ataReadLogExt(device, 0x11, features, 0, log_11, 1))
-          failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
-        else
-          PrintSataPhyEventCounters(log_11, options.sataphy_reset);
+      unsigned ns = req.nsectors;
+      if (ns > max_nsectors - req.page) {
+        if (req.nsectors != ~0U) // "FIRST-max"
+          pout("%s Log 0x%02x has only %u sectors, output truncated\n", type, req.logaddr, max_nsectors);
+        ns = max_nsectors - req.page;
       }
+
+      // SMART log don't support sector offset, start with first sector
+      unsigned offs = (req.gpl ? 0 : req.page);
+
+      raw_buffer log_buf((offs + ns) * 512);
+      bool ok;
+      if (req.gpl)
+        ok = ataReadLogExt(device, req.logaddr, 0x00, req.page, log_buf.data(), ns);
+      else
+        ok = ataReadSmartLog(device, req.logaddr, log_buf.data(), offs + ns);
+      if (!ok)
+        failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
+      else
+        PrintLogPages(type, log_buf.data() + offs*512, req.logaddr, req.page, ns, max_nsectors);
+    }
+  }
+
+  // Print SMART Extendend Comprehensive Error Log
+  if (options.smart_ext_error_log) {
+    unsigned nsectors = GetNumLogSectors(gplogdir, 0x03, true);
+    if (!nsectors)
+      pout("SMART Extended Comprehensive Error Log (GP Log 0x03) does not exist\n");
+    else if (nsectors >= 256)
+      pout("SMART Extended Comprehensive Error Log size %u not supported\n", nsectors);
+    else {
+      raw_buffer log_03_buf(nsectors * 512);
+      ata_smart_exterrlog * log_03 = (ata_smart_exterrlog *)log_03_buf.data();
+      if (!ataReadExtErrorLog(device, log_03, nsectors))
+        failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
+      else
+        PrintSmartExtErrorLog(log_03, nsectors, options.smart_ext_error_log);
     }
   }
 
@@ -2219,7 +2179,24 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
       PRINT_OFF(con);
     }
   }
-  
+
+  // Print SMART Extendend Self-test Log
+  if (options.smart_ext_selftest_log) {
+    unsigned nsectors = GetNumLogSectors(gplogdir, 0x07, true);
+    if (!nsectors)
+      pout("SMART Extended Self-test Log (GP Log 0x07) does not exist\n");
+    else if (nsectors >= 256)
+      pout("SMART Extended Self-test Log size %u not supported\n", nsectors);
+    else {
+      raw_buffer log_07_buf(nsectors * 512);
+      ata_smart_extselftestlog * log_07 = (ata_smart_extselftestlog *)log_07_buf.data();
+      if (!ataReadExtSelfTestLog(device, log_07, nsectors))
+        failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
+      else
+        PrintSmartExtSelfTestLog(log_07, nsectors, options.smart_ext_selftest_log);
+    }
+  }
+
   // Print SMART self-test log
   if (con->smartselftestlog){
     if (!isSmartTestLogCapable(&smartval, &drive)){
@@ -2314,6 +2291,16 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
     }
   }
 
+  // Print SATA Phy Event Counters
+  if (options.sataphy) {
+    unsigned char log_11[512] = {0, };
+    unsigned char features = (options.sataphy_reset ? 0x01 : 0x00);
+    if (!ataReadLogExt(device, 0x11, features, 0, log_11, 1))
+      failuretest(OPTIONAL_CMD, returnval|=FAILSMART);
+    else
+      PrintSataPhyEventCounters(log_11, options.sataphy_reset);
+  }
+
   // START OF THE TESTING SECTION OF THE CODE.  IF NO TESTING, RETURN
   if (con->testcase==-1)
     return returnval;
-- 
GitLab