LCOV - code coverage report
Current view: top level - examples - gopts.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 0 118 0.0 %
Date: 2019-09-12 12:28:41 Functions: 0 4 0.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  */
       8             : 
       9             : #include <kdb.h>
      10             : #include <kdbease.h>
      11             : #include <kdbhelper.h>
      12             : 
      13             : #include <kdbopts.h>
      14             : #include <stdio.h>
      15             : #include <stdlib.h>
      16             : 
      17             : extern char ** environ;
      18             : 
      19             : #define BASE_KEY "/sw/org/erm/#0/current"
      20             : #define SPEC_BASE_KEY "spec" BASE_KEY
      21             : 
      22             : // -----------------
      23             : // Helper methods
      24             : // -----------------
      25             : 
      26             : /*
      27             :  * The methods below are only used, so that this example is self-contained.
      28             :  * If you actually develop an application, you may use the `specload` plugin,
      29             :  * but in any case the specification should be mounted into the KDB using `kdb mount`.
      30             :  *
      31             :  * DO NOT set/unset the specification inside of your application.
      32             :  */
      33             : 
      34           0 : static KeySet * createSpec (void)
      35             : {
      36           0 :         return ksNew (
      37             :                 10,
      38             :                 keyNew (SPEC_BASE_KEY "/emptydirs", KEY_META, "description", "remove empty directories", KEY_META, "opt", "d", KEY_META,
      39             :                         "opt/arg", "none", KEY_META, "opt/long", "dir", KEY_END),
      40             :                 keyNew (SPEC_BASE_KEY "/force", KEY_META, "description", "ignore nonexistent files and arguments, never prompt", KEY_META,
      41             :                         "opt", "f", KEY_META, "opt/arg", "none", KEY_META, "opt/long", "force", KEY_END),
      42             :                 keyNew (SPEC_BASE_KEY "/interactive", KEY_META, "description",
      43             :                         "prompt according to WHEN: never, once (-I), or always (-i), without WHEN, prompt always", KEY_META, "opt", "#1",
      44             :                         KEY_META, "opt/#0", "i", KEY_META, "opt/#0/arg", "optional", KEY_META, "opt/#0/flagvalue", "always", KEY_META,
      45             :                         "opt/#0/long", "interactive", KEY_META, "opt/#1", "I", KEY_META, "opt/#1/arg", "none", KEY_META, "opt/#1/flagvalue",
      46             :                         "once", KEY_META, "opt/arg/name", "WHEN", KEY_END),
      47             :                 keyNew (SPEC_BASE_KEY "/nopreserve", KEY_META, "description", "do not treat '/' specially", KEY_META, "opt/arg", "none",
      48             :                         KEY_META, "opt/long", "no-preserve-root", KEY_END),
      49             :                 keyNew (SPEC_BASE_KEY "/preserve", KEY_META, "description",
      50             :                         "do not remove '/' (default), with 'all', reject any command line argument on a separate device from its parent",
      51             :                         KEY_META, "opt/arg", "optional", KEY_META, "opt/arg/name", "all", KEY_META, "opt/flagvalue", "root", KEY_META,
      52             :                         "opt/long", "preserve-root", KEY_END),
      53             :                 keyNew (SPEC_BASE_KEY "/recursive", KEY_META, "description", "remove directories and their contents recursively", KEY_META,
      54             :                         "opt", "#1", KEY_META, "opt/#0", "r", KEY_META, "opt/#0/arg", "none", KEY_META, "opt/#0/long", "recursive",
      55             :                         KEY_META, "opt/#1", "R", KEY_META, "opt/#1/arg", "none", KEY_END),
      56             :                 keyNew (SPEC_BASE_KEY "/showversion", KEY_META, "description", "output version information and exit", KEY_META, "opt/arg",
      57             :                         "none", KEY_META, "opt/long", "version", KEY_END),
      58             :                 keyNew (SPEC_BASE_KEY "/singlefs", KEY_META, "description",
      59             :                         "when removing a hierarchy recursively, skip any directory that is on a file system different from that of the "
      60             :                         "corresponding line argument",
      61             :                         KEY_META, "opt/arg", "none", KEY_META, "opt/long", "one-file-system", KEY_END),
      62             :                 keyNew (SPEC_BASE_KEY "/verbose", KEY_META, "description", "explain what is being done", KEY_META, "opt", "v", KEY_META,
      63             :                         "opt/arg", "none", KEY_META, "opt/long", "verbose", KEY_META, "env", "VERBOSE", KEY_END),
      64             :                 keyNew (SPEC_BASE_KEY "/files/#", KEY_META, "description", "the files that shall be deleted", KEY_META, "args", "remaining",
      65             :                         KEY_META, "env", "FILES", KEY_END),
      66             :                 KS_END);
      67             : }
      68             : 
      69           0 : static int setupSpec (void)
      70             : {
      71           0 :         Key * parentKey = keyNew (SPEC_BASE_KEY, KEY_END);
      72           0 :         KDB * kdb = kdbOpen (parentKey);
      73           0 :         KeySet * ks = ksNew (0, KS_END);
      74           0 :         kdbGet (kdb, ks, parentKey);
      75             : 
      76           0 :         KeySet * existing = ksCut (ks, parentKey);
      77           0 :         if (ksGetSize (existing) > 0)
      78             :         {
      79           0 :                 kdbClose (kdb, parentKey);
      80           0 :                 ksDel (ks);
      81           0 :                 ksDel (existing);
      82           0 :                 return 0;
      83             :         }
      84           0 :         ksDel (existing);
      85             : 
      86           0 :         KeySet * spec = createSpec ();
      87           0 :         ksAppend (ks, spec);
      88           0 :         ksDel (spec);
      89           0 :         kdbSet (kdb, ks, parentKey);
      90           0 :         kdbClose (kdb, parentKey);
      91           0 :         ksDel (ks);
      92             : 
      93           0 :         return 1;
      94             : }
      95             : 
      96           0 : static void removeSpec (void)
      97             : {
      98           0 :         Key * parentKey = keyNew (SPEC_BASE_KEY, KEY_END);
      99           0 :         KDB * kdb = kdbOpen (parentKey);
     100           0 :         KeySet * ks = ksNew (0, KS_END);
     101           0 :         kdbGet (kdb, ks, parentKey);
     102           0 :         KeySet * spec = ksCut (ks, parentKey);
     103           0 :         ksDel (spec);
     104           0 :         kdbSet (kdb, ks, parentKey);
     105           0 :         kdbClose (kdb, parentKey);
     106           0 :         ksDel (ks);
     107           0 : }
     108             : 
     109             : // -----------------
     110             : // Main example
     111             : // -----------------
     112             : 
     113           0 : int main (void)
     114             : {
     115           0 :         if (!setupSpec ())
     116             :         {
     117           0 :                 fprintf (stderr, "ERROR: Couldn't setup spec, keys exist!\n");
     118           0 :                 return EXIT_FAILURE;
     119             :         }
     120             : 
     121           0 :         Key * parentKey = keyNew (BASE_KEY, KEY_END);
     122           0 :         KDB * kdb = kdbOpen (parentKey);
     123             : 
     124           0 :         KeySet * contract = ksNew (1, keyNew ("system/elektra/ensure/plugins/global/gopts", KEY_VALUE, "mounted", KEY_END), KS_END);
     125           0 :         int rc = kdbEnsure (kdb, contract, parentKey);
     126           0 :         if (rc == 1)
     127             :         {
     128           0 :                 fprintf (stderr, "ERROR: Contract could not be ensured!\n%s\n", keyString (keyGetMeta (parentKey, "error/reason")));
     129           0 :                 kdbClose (kdb, parentKey);
     130           0 :                 keyDel (parentKey);
     131           0 :                 removeSpec ();
     132           0 :                 return EXIT_FAILURE;
     133             :         }
     134           0 :         else if (rc == -1)
     135             :         {
     136           0 :                 fprintf (stderr, "ERROR: Contract malformed/NULL pointer!\n%s\n", keyString (keyGetMeta (parentKey, "error/reason")));
     137           0 :                 kdbClose (kdb, parentKey);
     138           0 :                 keyDel (parentKey);
     139           0 :                 removeSpec ();
     140           0 :                 return EXIT_FAILURE;
     141             :         }
     142             : 
     143           0 :         KeySet * ks = ksNew (0, KS_END);
     144           0 :         rc = kdbGet (kdb, ks, parentKey);
     145             : 
     146           0 :         if (rc == -1)
     147             :         {
     148           0 :                 fprintf (stderr, "ERROR: kdbGet failed! %s\n", keyString (keyGetMeta (parentKey, "error/reason")));
     149           0 :                 kdbClose (kdb, parentKey);
     150           0 :                 keyDel (parentKey);
     151           0 :                 ksDel (ks);
     152           0 :                 removeSpec ();
     153           0 :                 return EXIT_FAILURE;
     154             :         }
     155             : 
     156           0 :         Key * helpKey = ksLookupByName (ks, "proc/elektra/gopts/help", 0);
     157           0 :         if (helpKey != NULL && elektraStrCmp (keyString (helpKey), "1") == 0)
     158             :         {
     159           0 :                 char * help = elektraGetOptsHelpMessage (helpKey, NULL, NULL);
     160           0 :                 printf ("%s\n", help);
     161           0 :                 elektraFree (help);
     162           0 :                 kdbClose (kdb, parentKey);
     163           0 :                 keyDel (parentKey);
     164           0 :                 ksDel (ks);
     165           0 :                 removeSpec ();
     166           0 :                 return EXIT_SUCCESS;
     167             :         }
     168             : 
     169           0 :         printf ("When called with the same arguments 'rm' \n");
     170             : 
     171           0 :         Key * lookup = ksLookupByName (ks, BASE_KEY "/emptydirs", 0);
     172           0 :         if (lookup != NULL && elektraStrCmp (keyString (lookup), "1") == 0)
     173             :         {
     174           0 :                 printf ("will delete empty directories\n");
     175             :         }
     176             : 
     177           0 :         lookup = ksLookupByName (ks, BASE_KEY "/force", 0);
     178           0 :         if (lookup != NULL && elektraStrCmp (keyString (lookup), "1") == 0)
     179             :         {
     180           0 :                 printf ("will use force mode\n");
     181             :         }
     182             : 
     183           0 :         lookup = ksLookupByName (ks, BASE_KEY "/interactive", 0);
     184           0 :         if (lookup != NULL && elektraStrCmp (keyString (lookup), "never") == 0)
     185             :         {
     186           0 :                 printf ("will not use interactive mode\n");
     187             :         }
     188           0 :         else if (lookup != NULL && elektraStrCmp (keyString (lookup), "once") == 0)
     189             :         {
     190           0 :                 printf ("will use interactive mode; ask once\n");
     191             :         }
     192           0 :         else if (lookup != NULL && elektraStrCmp (keyString (lookup), "always") == 0)
     193             :         {
     194           0 :                 printf ("will use interactive mode; always ask\n");
     195             :         }
     196             : 
     197           0 :         lookup = ksLookupByName (ks, BASE_KEY "/nopreserve", 0);
     198           0 :         if (lookup != NULL && elektraStrCmp (keyString (lookup), "1") == 0)
     199             :         {
     200           0 :                 printf ("will not treat '/' specially\n");
     201             :         }
     202             : 
     203           0 :         lookup = ksLookupByName (ks, BASE_KEY "/preserve", 0);
     204           0 :         if (lookup != NULL && elektraStrCmp (keyString (lookup), "root") == 0)
     205             :         {
     206           0 :                 printf ("will never remove '/'");
     207             :         }
     208           0 :         else if (lookup != NULL && elektraStrCmp (keyString (lookup), "all") == 0)
     209             :         {
     210           0 :                 printf ("will reject any argument on separate device from its parent\n");
     211             :         }
     212             : 
     213           0 :         lookup = ksLookupByName (ks, BASE_KEY "/recursive", 0);
     214           0 :         if (lookup != NULL && elektraStrCmp (keyString (lookup), "1") == 0)
     215             :         {
     216           0 :                 printf ("will delete recursively\n");
     217             :         }
     218             : 
     219           0 :         lookup = ksLookupByName (ks, BASE_KEY "/showversion", 0);
     220           0 :         if (lookup != NULL && elektraStrCmp (keyString (lookup), "1") == 0)
     221             :         {
     222           0 :                 printf ("will show version and exit\n");
     223             :         }
     224             : 
     225           0 :         lookup = ksLookupByName (ks, BASE_KEY "/singlefs", 0);
     226           0 :         if (lookup != NULL && elektraStrCmp (keyString (lookup), "1") == 0)
     227             :         {
     228           0 :                 printf ("will skip directories on different file systems\n");
     229             :         }
     230             : 
     231           0 :         lookup = ksLookupByName (ks, BASE_KEY "/verbose", 0);
     232           0 :         if (lookup != NULL && elektraStrCmp (keyString (lookup), "1") == 0)
     233             :         {
     234           0 :                 printf ("will explain what is being done\n");
     235             :         }
     236             : 
     237           0 :         printf ("will remove the following files:\n");
     238             : 
     239           0 :         Key * arrayParent = ksLookupByName (ks, BASE_KEY "/files", 0);
     240           0 :         KeySet * files = elektraArrayGet (arrayParent, ks);
     241             : 
     242           0 :         ksRewind (files);
     243           0 :         Key * cur = NULL;
     244           0 :         while ((cur = ksNext (files)) != NULL)
     245             :         {
     246           0 :                 printf ("  %s\n", keyString (cur));
     247             :         }
     248           0 :         printf ("\n");
     249             : 
     250           0 :         kdbClose (kdb, parentKey);
     251           0 :         keyDel (parentKey);
     252           0 :         ksDel (ks);
     253             : 
     254           0 :         removeSpec ();
     255             : 
     256           0 :         return EXIT_SUCCESS;
     257             : }

Generated by: LCOV version 1.13