File 0002-Simplify-and-fix-parsing-of-etc-SuSE-release-fixes-i.patch of Package cfengine

From 7b2bde90b9499920872723c733aea202f044d709 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Klaus=20K=C3=A4mpf?= <kkaempf@suse.de>
Date: Fri, 11 Apr 2014 09:25:05 +0200
Subject: [PATCH 2/3] Simplify and fix parsing of /etc/SuSE-release (fixes
 issue #5423)

This patch is a simplification of sysinfo.c:Linux_Suse_Version()
to achieve the following

- distinction between "SUSE Linux Enterprise Server" (sles) and "... Desktop" (sled)
- distinction between SUSE Linux Enterprise products (suse) and openSUSE (opensuse)
- extract version from VERSION and PATCHLEVEL lines instead of
  first line of /etc/SuSE-release
- verified for sles version 9,10,11,12; sled versions 10,11,12, openSUSE 13.1
---
 libenv/sysinfo.c | 187 ++++++++++++++++++-------------------------------------
 1 file changed, 60 insertions(+), 127 deletions(-)

diff --git a/libenv/sysinfo.c b/libenv/sysinfo.c
index 8bea42c7f7a7..b8fc9c76cf65 100644
--- a/libenv/sysinfo.c
+++ b/libenv/sysinfo.c
@@ -1822,6 +1822,7 @@ static int Linux_Suse_Version(EvalContext *ctx)
 #define SUSE_RELEASE_FLAG "linux "
 
     char classbuf[CF_MAXVARSIZE];
+    char *vendor = "suse";
 
     Log(LOG_LEVEL_VERBOSE, "This appears to be a SUSE system.");
     EvalContextClassPutHard(ctx, "SUSE", "inventory,attribute_name=none,source=agent");
@@ -1841,23 +1842,26 @@ static int Linux_Suse_Version(EvalContext *ctx)
         return 1;
     }
 
-    char vbuf[CF_BUFSIZE], strversion[CF_MAXVARSIZE], strpatch[CF_MAXVARSIZE];
-    strversion[0] = '\0';
-    strpatch[0] = '\0';
+    char vbuf[CF_BUFSIZE];
 
     int major = -1, minor = -1;
     while (fgets(vbuf, sizeof(vbuf), fp) != NULL)
     {
         if (strncmp(vbuf, "VERSION", strlen("version")) == 0)
         {
-            strlcpy(strversion, vbuf, sizeof(strversion));
-            sscanf(vbuf, "VERSION = %d", &major);
+            int res;
+            res = sscanf(vbuf, "VERSION = %d.%d", &major, &minor);
+            Log(LOG_LEVEL_VERBOSE, "VERSION sscanf returned %d.", res);
+            if (res < 1)
+                major = -1;
+            else if (res < 2)
+                minor = -1;
         }
 
         if (strncmp(vbuf, "PATCH", strlen("PATCH")) == 0)
         {
-            strlcpy(strpatch, vbuf, sizeof(strpatch));
-            sscanf(vbuf, "PATCHLEVEL = %d", &minor);
+            if (sscanf(vbuf, "PATCHLEVEL = %d", &minor) != 1)
+                minor = -1;
         }
     }
     if (ferror(fp))
@@ -1871,28 +1875,38 @@ static int Linux_Suse_Version(EvalContext *ctx)
 
     fclose(fp);
 
-    /* Check if it's a SUSE Enterprise version  */
+    /* Check which SUSE/openSUSE product it is  */
 
-    Log(LOG_LEVEL_VERBOSE, "Looking for SUSE enterprise info in '%s'", relstring);
+    Log(LOG_LEVEL_VERBOSE, "Looking for SUSE product info in '%s'", relstring);
 
-    /* Convert relstring to lowercase to handle rename of SuSE to
-     * SUSE with SUSE 10.0.
-     */
-
-    for (int i = 0; i < strlen(relstring); i++)
+    if (!strncasecmp(relstring, SUSE_SLES8_ID, strlen(SUSE_SLES8_ID)))
     {
-        relstring[i] = tolower(relstring[i]);
+        EvalContextClassPutHard(ctx, "SLES8", "inventory,attribute_name=none,source=agent");
     }
-
-    /* Check if it's a SUSE Enterprise version (all in lowercase) */
-
-    if (!strncmp(relstring, SUSE_SLES8_ID, strlen(SUSE_SLES8_ID)))
+    else if (!strncasecmp(relstring, SUSE_SLES_ID, strlen(SUSE_SLES_ID)))
     {
-        classbuf[0] = '\0';
-        strcat(classbuf, "SLES8");
-        EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent");
+        EvalContextClassPutHard(ctx, "sles", "inventory,attribute_name=none,source=agent");
+        if (major != -1)
+        {
+            snprintf(classbuf, CF_MAXVARSIZE, "SLES%d", major);
+            EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent");
+        }
+    }
+    else if (!strncasecmp(relstring, SUSE_SLED_ID, strlen(SUSE_SLED_ID)))
+    {
+        EvalContextClassPutHard(ctx, "sled", "inventory,attribute_name=none,source=agent");
+        if (major != -1)
+        {
+            snprintf(classbuf, CF_MAXVARSIZE, "SLED%d", major);
+            EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent");
+        }
+    }
+    else if (!strncasecmp(relstring, "opensuse", strlen("opensuse")))
+    {
+        vendor = "opensuse";
+        EvalContextClassPutHard(ctx, vendor, "inventory,attribute_name=none,source=agent");
     }
-    else if (strncmp(relstring, "sles", 4) == 0)
+    else if (strncasecmp(relstring, "sles", 4) == 0)
     {
         Item *list, *ip;
 
@@ -1910,120 +1924,39 @@ static int Linux_Suse_Version(EvalContext *ctx)
     }
     else
     {
-        for (int version = 9; version < 13; version++)
-        {
-            snprintf(vbuf, CF_BUFSIZE, "%s %d ", SUSE_SLES_ID, version);
-            Log(LOG_LEVEL_DEBUG, "Checking for SUSE [%s]", vbuf);
-
-            if (!strncmp(relstring, vbuf, strlen(vbuf)))
-            {
-                snprintf(classbuf, CF_MAXVARSIZE, "SLES%d", version);
-                EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent");
-            }
-            else
-            {
-                snprintf(vbuf, CF_BUFSIZE, "%s %d ", SUSE_SLED_ID, version);
-                Log(LOG_LEVEL_DEBUG, "Checking for SUSE [%s]", vbuf);
-
-                if (!strncmp(relstring, vbuf, strlen(vbuf)))
-                {
-                    snprintf(classbuf, CF_MAXVARSIZE, "SLED%d", version);
-                    EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent");
-                }
-            }
-        }
+        Log(LOG_LEVEL_WARNING, "Unknown product '%s' in /etc/SuSE-release", relstring);
     }
 
-    /* Determine release version. We assume that the version follows
-     * the string "SuSE Linux" or "SUSE LINUX".
-     */
-
-    char *release = strstr(relstring, SUSE_RELEASE_FLAG);
-    if (release == NULL)
+    if (major != -1)
     {
-        release = strstr(relstring, "opensuse");
-        if (release == NULL)
+        strncpy(classbuf, vendor, CF_MAXVARSIZE);
+        EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent");
+        snprintf(classbuf + strlen(classbuf), CF_MAXVARSIZE - strlen(classbuf), "_%d", major);
+        SetFlavour(ctx, classbuf);
+        if (minor != -1)
         {
-            release = strversion;
+            snprintf(classbuf + strlen(classbuf), CF_MAXVARSIZE - strlen(classbuf), "_%d", minor);
+            EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent");
         }
-    }
-
-    if (release == NULL)
-    {
-        Log(LOG_LEVEL_VERBOSE,
-            "Could not find a numeric OS release in %s",
-            SUSE_REL_FILENAME);
-        return 2;
+        /* The correct spelling for SUSE is "SUSE" but CFEngine used to use "SuSE".
+         * Keep this for backwards compatibility until CFEngine 3.7
+         */
+        strncpy(classbuf, "SuSE", CF_MAXVARSIZE);
+        EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent");
+        snprintf(classbuf + strlen(classbuf), CF_MAXVARSIZE - strlen(classbuf), "_%d", major);
+        EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent");
+        if (minor != -1)
+        {
+            snprintf(classbuf + strlen(classbuf), CF_MAXVARSIZE - strlen(classbuf), "_%d", minor);
+            EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent");
+        }
+        Log(LOG_LEVEL_VERBOSE, "Discovered %s version %d.%d", vendor, major, minor);
     }
     else
     {
-        char strmajor[PRINTSIZE(major)], strminor[PRINTSIZE(minor)];
-        if (strchr(release, '.'))
-        {
-            sscanf(release, "%*s %d.%d", &major, &minor);
-            xsnprintf(strmajor, sizeof(strmajor), "%d", major);
-            xsnprintf(strminor, sizeof(strminor), "%d", minor);
-
-            if (major != -1 && minor != -1)
-            {
-                strcpy(classbuf, "SUSE");
-                EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent");
-                strcat(classbuf, "_");
-                strcat(classbuf, strmajor);
-                SetFlavour(ctx, classbuf);
-                strcat(classbuf, "_");
-                strcat(classbuf, strminor);
-                EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent");
-
-                /* The correct spelling for SUSE is "SUSE" but CFEngine used to use "SuSE".
-                 * Keep this for backwards compatibility until CFEngine 3.7
-                 */
-                strcpy(classbuf, "SuSE");
-                EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent");
-                strcat(classbuf, "_");
-                strcat(classbuf, strmajor);
-                EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent");
-                strcat(classbuf, "_");
-                strcat(classbuf, strminor);
-                EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent");
-
-                Log(LOG_LEVEL_VERBOSE, "Discovered SUSE version %s", classbuf);
-                return 0;
-            }
-        }
-        else
-        {
-            sscanf(strversion, "VERSION = %s", strmajor);
-            sscanf(strpatch, "PATCHLEVEL = %s", strminor);
-
-            if (major != -1 && minor != -1)
-            {
-                strcpy(classbuf, "SLES");
-                EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent");
-                strcat(classbuf, "_");
-                strcat(classbuf, strmajor);
-                EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent");
-                strcat(classbuf, "_");
-                strcat(classbuf, strminor);
-                EvalContextClassPutHard(ctx, classbuf, "inventory,attribute_name=none,source=agent");
-
-                snprintf(classbuf, CF_MAXVARSIZE, "SUSE_%d", major);
-                SetFlavour(ctx, classbuf);
-
-                /* The correct spelling for SUSE is "SUSE" but CFEngine used to use "SuSE".
-                 * Keep this for backwards compatibility until CFEngine 3.7
-                 */
-                snprintf(classbuf, CF_MAXVARSIZE, "SuSE_%d", major);
-                EvalContextClassPutHard(ctx, classbuf, "source=agent");
-
-                Log(LOG_LEVEL_VERBOSE, "Discovered SUSE version %s", classbuf);
-                return 0;
-            }
-        }
+        Log(LOG_LEVEL_VERBOSE, "Could not find a numeric OS release in %s", SUSE_REL_FILENAME);
     }
 
-    Log(LOG_LEVEL_VERBOSE, "Could not find a numeric OS release in %s", SUSE_REL_FILENAME);
-
     return 0;
 }
 
-- 
2.15.0