LCOV - code coverage report
Current view: top level - src/plugins/unit - unit.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 68 71 95.8 %
Date: 2019-09-12 12:28:41 Functions: 6 7 85.7 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief unit plugin
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  *
       8             :  */
       9             : 
      10             : #include "unit.h"
      11             : #include <kdberrors.h>
      12             : #include <kdbhelper.h>
      13             : #include <kdbtypes.h>
      14             : #include <stdio.h>
      15             : #include <stdlib.h>
      16             : 
      17             : // @param input string, of which possibly occurring spaces are removed
      18             : static void deblank (char * input)
      19             : {
      20             :         int count = 0;
      21             : 
      22         144 :         for (int i = 0; input[i]; i++)
      23             :         {
      24         144 :                 if (input[i] != ' ')
      25             :                 {
      26         130 :                         input[count++] = input[i];
      27             :                 }
      28             :         }
      29             : 
      30          58 :         input[count] = '\0';
      31             : }
      32             : 
      33          72 : static kdb_unsigned_long_long_t isValidKey (Key * key)
      34             : {
      35             : 
      36          72 :         const char * value = keyString (key);
      37             :         // else we manipulate the original
      38          72 :         char * tempval = elektraStrDup (value);
      39             : 
      40             :         char * endPtr;
      41             : 
      42             : 
      43             :         // convert to long, if valid key, pointer should point to spaces or unit suffix like MB, GB
      44          72 :         ELEKTRA_UNSIGNED_LONG_LONG_S (tempval, &endPtr, 10);
      45             : 
      46             :         // before deblanking check if pointer is invalid
      47          72 :         if (endPtr == tempval)
      48             :         {
      49          14 :                 elektraFree (tempval);
      50          14 :                 return 0;
      51             :         }
      52             : 
      53             :         // remove possibly occurring blanks
      54          58 :         deblank (endPtr);
      55          58 :         kdb_unsigned_long_long_t factor = 0;
      56             : 
      57             :         // calculate the factor based on the suffix of the mameory value, return 0 if there is no matching to indicate an error of the
      58             :         // function
      59          58 :         if (strcmp (endPtr, "KB") == 0)
      60             :         {
      61             :                 factor = 1000;
      62             :         }
      63          58 :         else if (strcmp (endPtr, "MB") == 0)
      64             :         {
      65             :                 factor = 1000000;
      66             :         }
      67          42 :         else if (strcmp (endPtr, "GB") == 0)
      68             :         {
      69             :                 factor = 1000000000;
      70             :         }
      71          38 :         else if (strcmp (endPtr, "TB") == 0)
      72             :         {
      73             :                 factor = 1000000000000;
      74             :         }
      75          34 :         else if (strcmp (endPtr, "PB") == 0)
      76             :         {
      77             :                 factor = 1000000000000000;
      78             :         }
      79          26 :         else if (strcmp (endPtr, "B") == 0)
      80             :         {
      81           8 :                 factor = 1;
      82             :         }
      83             : 
      84          58 :         elektraFree (tempval);
      85          58 :         return factor;
      86             : }
      87             : 
      88             : // @param formatFactor unsigned long, used to determine the factor for normalizing to bytes
      89          18 : static int elektraUnitConvertToByteString (Key * key, kdb_unsigned_long_long_t formatFactor)
      90          18 : {
      91             : 
      92          18 :         const char * str = keyString (key);
      93          18 :         char * origvalue = elektraStrDup (str);
      94             :         char * ptr;
      95             :         kdb_unsigned_long_long_t ret;
      96             :         kdb_unsigned_long_long_t normalizedMemVal;
      97             : 
      98          18 :         ret = ELEKTRA_UNSIGNED_LONG_LONG_S (str, &ptr, 10);
      99             : 
     100             :         // check if return value within bounds
     101          18 :         if (ret > UINT64_MAX / formatFactor)
     102             :         {
     103           0 :                 elektraFree (origvalue);
     104           0 :                 return 1;
     105             :         }
     106             : 
     107          18 :         normalizedMemVal = ret * formatFactor;
     108             : 
     109             :         // convert back to string
     110          18 :         const int n = snprintf (NULL, 0, ELEKTRA_UNSIGNED_LONG_LONG_F, normalizedMemVal);
     111          18 :         char buf[n + 1];
     112             : 
     113          18 :         snprintf (buf, n + 1, ELEKTRA_UNSIGNED_LONG_LONG_F, normalizedMemVal);
     114             : 
     115          18 :         keySetString (key, buf);
     116          18 :         keySetMeta (key, "origvalue", origvalue);
     117          18 :         elektraFree (origvalue);
     118          18 :         return 0;
     119             : }
     120             : 
     121          42 : static void elektraUnitRestore (Key * key)
     122             : {
     123          42 :         const Key * oldval = keyGetMeta (key, "origvalue");
     124          42 :         if (oldval != NULL)
     125             :         {
     126          18 :                 keySetString (key, keyString (oldval));
     127             :         }
     128          42 : }
     129             : 
     130             : 
     131          50 : int elektraUnitGet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned, Key * parentKey)
     132             : {
     133          50 :         if (!elektraStrCmp (keyName (parentKey), "system/elektra/modules/unit"))
     134             :         {
     135          20 :                 KeySet * contract =
     136          20 :                         ksNew (30, keyNew ("system/elektra/modules/unit", KEY_VALUE, "unit plugin waits for your orders", KEY_END),
     137             :                                keyNew ("system/elektra/modules/unit/exports", KEY_END),
     138             :                                keyNew ("system/elektra/modules/unit/exports/get", KEY_FUNC, elektraUnitGet, KEY_END),
     139             :                                keyNew ("system/elektra/modules/unit/exports/set", KEY_FUNC, elektraUnitSet, KEY_END),
     140             : #include ELEKTRA_README
     141             :                                keyNew ("system/elektra/modules/unit/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END);
     142          20 :                 ksAppend (returned, contract);
     143          20 :                 ksDel (contract);
     144             : 
     145          20 :                 return ELEKTRA_PLUGIN_STATUS_SUCCESS;
     146             :         }
     147             : 
     148             :         Key * cur;
     149             :         int rc = 1;
     150          48 :         while ((cur = ksNext (returned)) != NULL)
     151             :         {
     152          30 :                 const Key * meta = keyGetMeta (cur, "check/unit");
     153          30 :                 if (meta)
     154             :                 {
     155          30 :                         kdb_unsigned_long_long_t format = isValidKey (cur);
     156             : 
     157          30 :                         if (format == 0)
     158             :                         {
     159          12 :                                 ELEKTRA_SET_VALIDATION_SYNTACTIC_ERRORF (
     160             :                                         parentKey,
     161             :                                         "The string '%s' is not following the format guidelines of (<numerical value><optional "
     162             :                                         "space><memory unit>, e.g. 128 MB) !",
     163             :                                         keyString (cur));
     164          12 :                                 return ELEKTRA_PLUGIN_STATUS_ERROR;
     165             :                         }
     166          18 :                         elektraUnitConvertToByteString (cur, format);
     167             :                 }
     168             :         }
     169             :         return rc;
     170             : }
     171             : 
     172          42 : int elektraUnitSet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned ELEKTRA_UNUSED, Key * parentKey ELEKTRA_UNUSED)
     173             : {
     174             : 
     175             :         Key * cur;
     176          42 :         ksRewind (returned);
     177         106 :         while ((cur = ksNext (returned)) != NULL)
     178             :         {
     179          42 :                 const Key * meta = keyGetMeta (cur, "check/unit");
     180          42 :                 if (!meta)
     181             :                 {
     182           0 :                         continue;
     183             :                 }
     184             : 
     185          42 :                 elektraUnitRestore (cur);
     186          42 :                 kdb_unsigned_long_long_t format = isValidKey (cur);
     187             : 
     188          42 :                 if (format == 0)
     189             :                 {
     190          20 :                         ELEKTRA_SET_VALIDATION_SYNTACTIC_ERRORF (parentKey,
     191             :                                                                  "The string '%s' is not following the format guidelines of (<numerical "
     192             :                                                                  "value><optional space><memory unit>, "
     193             :                                                                  "e.g. 128 MB) !",
     194             :                                                                  keyString (cur));
     195          20 :                         return ELEKTRA_PLUGIN_STATUS_ERROR;
     196             :                 }
     197             :         }
     198             :         return ELEKTRA_PLUGIN_STATUS_SUCCESS;
     199             : }
     200             : 
     201             : 
     202          62 : Plugin * ELEKTRA_PLUGIN_EXPORT
     203             : {
     204          62 :         return elektraPluginExport ("unit", ELEKTRA_PLUGIN_GET, &elektraUnitGet, ELEKTRA_PLUGIN_SET, &elektraUnitSet, ELEKTRA_PLUGIN_END);
     205             : }

Generated by: LCOV version 1.13