From ed0c05584307d7fdabe37c4a737eef37cff366e5 Mon Sep 17 00:00:00 2001
From: chrfranke <chrfranke@4ea69e1a-61f1-4043-bf83-b5c94c648137>
Date: Thu, 15 Jan 2009 22:52:50 +0000
Subject: [PATCH] Fix smartctl crash on '-l directory,[gs]'. Allow to override
 missing GPL feature bit or missing log dir entry with '-T permissive' option.

git-svn-id: https://smartmontools.svn.sourceforge.net/svnroot/smartmontools/trunk@2705 4ea69e1a-61f1-4043-bf83-b5c94c648137
---
 sm5/CHANGELOG    |  6 +++++-
 sm5/ataprint.cpp | 52 +++++++++++++++++++++++++++++++-----------------
 2 files changed, 39 insertions(+), 19 deletions(-)

diff --git a/sm5/CHANGELOG b/sm5/CHANGELOG
index 158eca100..0831f3198 100644
--- a/sm5/CHANGELOG
+++ b/sm5/CHANGELOG
@@ -1,6 +1,6 @@
 CHANGELOG for smartmontools
 
-$Id: CHANGELOG,v 1.761 2009/01/14 02:39:00 sxzzsf Exp $
+$Id: CHANGELOG,v 1.762 2009/01/15 22:52:50 chrfranke Exp $
 
 The most recent version of this file is:
 http://smartmontools.cvs.sourceforge.net/smartmontools/sm5/CHANGELOG?view=markup
@@ -41,6 +41,10 @@ NOTES FOR FUTURE RELEASES: see TODO file.
 
 <DEVELOPERS: ADDITIONS TO THE CHANGE LOG GO JUST BELOW HERE, PLEASE>
 
+  [CF] Fix smartctl crash on '-l directory,[gs]'. Allow to override
+       missing GPL feature bit or missing log dir entry with
+       '-T permissive' option.
+
   [SZ] os_freebsd.cpp, os_freebsd.h updates:
        Support HighPoint RocketRAID controller under FreeBSD
 
diff --git a/sm5/ataprint.cpp b/sm5/ataprint.cpp
index 7e1c99297..9d5777bcc 100644
--- a/sm5/ataprint.cpp
+++ b/sm5/ataprint.cpp
@@ -43,7 +43,7 @@
 #include "utility.h"
 #include "knowndrives.h"
 
-const char *ataprint_c_cvsid="$Id: ataprint.cpp,v 1.203 2008/10/11 14:18:07 chrfranke Exp $"
+const char *ataprint_c_cvsid="$Id: ataprint.cpp,v 1.204 2009/01/15 22:52:50 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
@@ -859,15 +859,17 @@ static void ataPrintGeneralSmartValues(const ata_smart_values *data, const ata_i
 // Get # sectors of a log addr, 0 if log does not exist.
 static unsigned GetNumLogSectors(const ata_smart_log_directory * logdir, unsigned logaddr, bool gpl)
 {
-    if (logaddr > 0xff)
-      return 0;
-    if (logaddr == 0)
-      return 1;
-    unsigned n = logdir->entry[logaddr-1].numsectors;
-    if (gpl)
-        // GP logs may have >255 sectors
-        n |= logdir->entry[logaddr-1].reserved << 8;
-    return n;
+  if (!logdir)
+    return 0;
+  if (logaddr > 0xff)
+    return 0;
+  if (logaddr == 0)
+    return 1;
+  unsigned n = logdir->entry[logaddr-1].numsectors;
+  if (gpl)
+    // GP logs may have >255 sectors
+    n |= logdir->entry[logaddr-1].reserved << 8;
+  return n;
 }
 
 // Get name of log.
@@ -932,7 +934,7 @@ static void PrintLogDirectories(const ata_smart_log_directory * gplogdir,
       if (gp_numsect)
         pout("GP %sLog at address 0x%02x has %4d sectors [%s]\n", (smartlogdir?"   ":""),
              i, gp_numsect, name);
-      if (smart_numsect )
+      if (smart_numsect)
         pout("SMART Log at address 0x%02x has %4d sectors [%s]\n", i, smart_numsect, name);
     }
   }
@@ -1780,13 +1782,23 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
   if (   options.gp_logdir || options.smart_logdir
       || options.sataphy
       || !options.log_requests.empty()            ) {
-    if (!isGeneralPurposeLoggingCapable(&drive)) {
-      pout("Warning: device does not support General Purpose Logging\n");
+
+    bool gpl_cap = !!isGeneralPurposeLoggingCapable(&drive);
+    bool gpl_try = gpl_cap;
+    if (!gpl_try && con->permissive) {
+        con->permissive--;
+        gpl_try = 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);
-      pout("General Purpose Logging supported\n");
+      if (gpl_cap)
+        pout("General Purpose Logging (GPL) feature set supported\n");
 
       // Detect directories needed
       bool need_smart_logdir = options.smart_logdir;
@@ -1839,16 +1851,20 @@ int ataPrintMain (ata_device * device, const ata_print_options & options)
         unsigned max_nsectors;
         if (req.gpl) {
           type = "General Purpose";
-          max_nsectors = (gplogdir ? GetNumLogSectors(gplogdir, req.logaddr, true) : 0);
+          max_nsectors = GetNumLogSectors(gplogdir, req.logaddr, true);
         }
         else {
           type = "SMART";
-          max_nsectors = (smartlogdir ? GetNumLogSectors(smartlogdir, req.logaddr, false) : 0);
+          max_nsectors = GetNumLogSectors(smartlogdir, req.logaddr, false);
         }
 
         if (!max_nsectors) {
-          pout("%s Log 0x%02x does not exist\n", type, req.logaddr);
-          continue;
+          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);
-- 
GitLab