LCOV - code coverage report
Current view: top level - src/plugins/hosts - hosts-set.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 79 85 92.9 %
Date: 2019-09-12 12:28:41 Functions: 7 7 100.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief Contains the set direction of the hosts plugin
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  *
       8             :  */
       9             : 
      10             : #include "hosts.h"
      11             : 
      12             : #ifndef HAVE_KDBCONFIG
      13             : #include "kdbconfig.h"
      14             : #endif
      15             : 
      16             : #include <kdbextension.h>
      17             : #include <kdbproposal.h>
      18             : 
      19          64 : static int keyCmpOrderWrapper (const void * a, const void * b)
      20             : {
      21          64 :         return elektraKeyCmpOrder (*((const Key **) a), *((const Key **) b));
      22             : }
      23             : 
      24          50 : static void writeComment (const char * spaces, const char * start, const char * comment, FILE * fp)
      25             : {
      26          50 :         if (spaces)
      27             :         {
      28             :                 char * endptr;
      29           8 :                 long spaceValue = strtol (spaces, &endptr, 10);
      30             : 
      31           8 :                 if (*endptr == '\0')
      32             :                 {
      33          16 :                         for (int i = 0; i < spaceValue; i++)
      34             :                         {
      35          16 :                                 fprintf (fp, " ");
      36             :                         }
      37             :                 }
      38             :         }
      39             : 
      40          50 :         if (start)
      41             :         {
      42          14 :                 fprintf (fp, "%s", start);
      43             :         }
      44             : 
      45          50 :         if (comment)
      46             :         {
      47          33 :                 fprintf (fp, "%s", comment);
      48             :         }
      49          50 : }
      50             : 
      51         150 : static const char * getMetaValue (Key * key, const char * metaName)
      52             : {
      53         150 :         const Key * metaKey = keyGetMeta (key, metaName);
      54             : 
      55         150 :         if (metaKey) return keyString (metaKey);
      56             : 
      57             :         return 0;
      58             : }
      59             : 
      60          54 : static void writeLineComments (Key * key, FILE * fp)
      61             : {
      62             :         // TODO: this is really inefficient
      63          54 :         KeySet * metaKeys = elektraKeyGetMetaKeySet (key);
      64          54 :         Key * commentParent = keyNew ("comment", KEY_META_NAME, KEY_END);
      65          54 :         KeySet * comments = elektraArrayGet (commentParent, metaKeys);
      66          54 :         keyDel (commentParent);
      67             : 
      68          54 :         ksRewind (comments);
      69             :         Key * current;
      70         141 :         while ((current = ksNext (comments)))
      71             :         {
      72          33 :                 if (strcmp (keyName (current), "comment/#0"))
      73             :                 {
      74          20 :                         Key * spaceKey = keyDup (current);
      75          20 :                         keyAddBaseName (spaceKey, "space");
      76          20 :                         Key * startKey = keyDup (current);
      77          20 :                         keyAddBaseName (startKey, "start");
      78          20 :                         const char * spaces = getMetaValue (key, keyName (spaceKey));
      79          20 :                         const char * start = getMetaValue (key, keyName (startKey));
      80          20 :                         const char * comment = getMetaValue (key, keyName (current));
      81          20 :                         keyDel (spaceKey);
      82          20 :                         keyDel (startKey);
      83          20 :                         writeComment (spaces, start, comment, fp);
      84          20 :                         fprintf (fp, "\n");
      85             :                 }
      86             :         }
      87             : 
      88          54 :         ksDel (metaKeys);
      89          54 :         ksDel (comments);
      90          54 : }
      91             : 
      92          30 : static void writeInlineComment (Key * key, FILE * fp)
      93             : {
      94             : 
      95          30 :         const char * spaces = getMetaValue (key, "comment/#0/space");
      96          30 :         const char * start = getMetaValue (key, "comment/#0/start");
      97          30 :         const char * comment = getMetaValue (key, "comment/#0");
      98             : 
      99          30 :         writeComment (spaces, start, comment, fp);
     100          30 : }
     101             : 
     102          30 : static void writeHostsEntry (Key * key, KeySet * returned, FILE * fp)
     103             : {
     104          30 :         fprintf (fp, "%s\t%s", (char *) keyValue (key), (char *) keyBaseName (key));
     105             :         /* position the cursor at the current key and
     106             :          * iterate over its subkeys
     107             :          */
     108          30 :         ksLookup (returned, key, KDB_O_NONE);
     109             :         Key * alias;
     110          70 :         while ((alias = ksNext (returned)) != 0)
     111             :         {
     112          24 :                 if (keyRel (key, alias) < 1) break;
     113             : 
     114          10 :                 fprintf (fp, " %s", (char *) keyBaseName (alias));
     115             :         }
     116          30 : }
     117             : 
     118          24 : int elektraHostsSet (Plugin * handle ELEKTRA_UNUSED, KeySet * returned, Key * parentKey)
     119             : {
     120          24 :         int errnosave = errno;
     121             :         FILE * fp;
     122             : 
     123          24 :         fp = fopen (keyString (parentKey), "w");
     124             : 
     125          24 :         if (fp == 0)
     126             :         {
     127           0 :                 ELEKTRA_SET_ERROR_SET (parentKey);
     128           0 :                 errno = errnosave;
     129           0 :                 return -1;
     130             :         }
     131             : 
     132             :         /* build an array of entries and sort them according to their order metadata */
     133             :         Key ** keyArray;
     134          24 :         size_t arraySize = ksGetSize (returned);
     135          24 :         keyArray = calloc (arraySize, sizeof (Key *));
     136             : 
     137          24 :         ksRewind (returned);
     138          24 :         int ret = elektraKsToMemArray (returned, keyArray);
     139             : 
     140          24 :         if (ret < 0)
     141             :         {
     142           0 :                 ELEKTRA_SET_RESOURCE_ERROR (parentKey, strerror (errno));
     143           0 :                 fclose (fp);
     144           0 :                 return -1;
     145             :         }
     146             : 
     147          24 :         qsort (keyArray, arraySize, sizeof (Key *), keyCmpOrderWrapper);
     148             : 
     149          24 :         Key * ipv4Base = keyDup (parentKey);
     150          24 :         keyAddBaseName (ipv4Base, "ipv4");
     151          24 :         Key * ipv6Base = keyDup (parentKey);
     152          24 :         keyAddBaseName (ipv6Base, "ipv6");
     153             : 
     154             :         /* now write the hosts file */
     155          86 :         for (size_t i = 0; i < arraySize; ++i)
     156             :         {
     157          62 :                 Key * key = keyArray[i];
     158             : 
     159             :                 /* only process canonical name keys */
     160          62 :                 if (!keyIsDirectBelow (ipv4Base, key) && !keyIsDirectBelow (ipv6Base, key)) continue;
     161             : 
     162          30 :                 writeLineComments (key, fp);
     163          30 :                 writeHostsEntry (key, returned, fp);
     164          30 :                 writeInlineComment (key, fp);
     165          30 :                 fprintf (fp, "\n");
     166             :         }
     167             : 
     168          24 :         writeLineComments (parentKey, fp);
     169             : 
     170          24 :         keyDel (ipv4Base);
     171          24 :         keyDel (ipv6Base);
     172             : 
     173          24 :         fclose (fp);
     174          24 :         errno = errnosave;
     175          24 :         elektraFree (keyArray);
     176          24 :         return 1;
     177             : }

Generated by: LCOV version 1.13