LCOV - code coverage report
Current view: top level - src/plugins/xmltool - stream.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 0 153 0.0 %
Date: 2019-09-12 12:28:41 Functions: 0 5 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 "xmltool.h"
      10             : 
      11             : #ifdef HAVE_KDBCONFIG_H
      12             : #include "kdbconfig.h"
      13             : #endif
      14             : 
      15             : #include <stdio.h>
      16             : #include <stdlib.h>
      17             : #include <string.h>
      18             : #include <time.h>
      19             : #include <unistd.h>
      20             : 
      21             : #include "kdbtools.h"
      22             : #include <kdbinternal.h>
      23             : 
      24             : 
      25             : /**
      26             :  * @brief Methods to output, generate and toXML Keys and Keysets.
      27             :  *
      28             :  * Here are some functions that are in a separate library because they
      29             :  * depend on non-basic libraries as libxml. Link against kdbtools library if your
      30             :  * program won't be installed in /bin, or is not essential in early boot
      31             :  * stages.
      32             :  *
      33             :  * It is also possible to have a dynamic linkage, see the
      34             :  * sourcecode from kdb-tool or testing framework how to achieve
      35             :  * that.
      36             :  *
      37             :  * Output prints keys line per line, meant to be read by humans.
      38             :  * - keyOutput()
      39             :  * - ksOutput()
      40             :  *
      41             :  * toXML prints keys and keysets as XML, meant to be used
      42             :  * as exchange format.
      43             :  * - keyToStream()
      44             :  * - ksToStream()
      45             :  *
      46             :  * To use them:
      47             :  * @code
      48             : #include <kdbtools.h>
      49             :  * @endcode
      50             :  *
      51             :  *
      52             :  */
      53             : 
      54             : 
      55             : /*********************************************
      56             :  *    Textual XML methods                    *
      57             :  *********************************************/
      58             : 
      59             : 
      60             : /**
      61             :  * Prints an XML representation of the key.
      62             :  *
      63             :  * String generated is of the form:
      64             :  * @verbatim
      65             :         <key name="system/sw/xorg/Monitor/Monitor0/Name"
      66             :                 type="string" uid="root" gid="root" mode="0600">
      67             : 
      68             :                 <value>Samsung TFT panel</value>
      69             :                 <comment>My monitor</comment>
      70             :         </key>@endverbatim
      71             : 
      72             : 
      73             : 
      74             :  * @verbatim
      75             :         <key parent="system/sw/xorg/Monitor/Monitor0" basename="Name"
      76             :                 type="string" uid="root" gid="root" mode="0600">
      77             : 
      78             :                 <value>Samsung TFT panel</value>
      79             :                 <comment>My monitor</comment>
      80             :         </key>@endverbatim
      81             :  *
      82             :  * @param key the key object to work with
      83             :  * @param stream where to write output: a file or stdout
      84             :  * @param options Some #option_t ORed:
      85             :  * - @p option_t::KDB_O_NUMBERS \n
      86             :  *   Do not convert UID and GID into user and group names
      87             :  * - @p option_t::KDB_O_CONDENSED \n
      88             :  *   Less human readable, more condensed output
      89             :  * - @p option_t::KDB_O_FULLNAME \n
      90             :  *   The @p user keys are exported with their full names (including
      91             :  *   user domains)
      92             :  *
      93             :  * @see ksToStream()
      94             :  * @return number of bytes written to output
      95             :  */
      96           0 : ssize_t keyToStream (const Key * key, FILE * stream, option_t options)
      97             : {
      98           0 :         return keyToStreamBasename (key, stream, 0, 0, options);
      99             : }
     100             : 
     101             : 
     102             : /**
     103             :  * Same as keyToStream() but tries to strip @p parentSize bytes from
     104             :  * @p key name if it matches @p parent .
     105             :  *
     106             :  * Taking the example from keyToStream(), if @p parent is
     107             :  * @c "system/sw/xorg", the generated string is of the form:
     108             :  * @verbatim
     109             :         <key basename="Monitor/Monitor0/Name"
     110             :                 type="string" uid="root" gid="root" mode="0600">
     111             : 
     112             :                 <value>Samsung TFT panel</value>
     113             :                 <comment>My monitor</comment>
     114             :         </key>@endverbatim
     115             :  *
     116             :  * It useful to produce more human readable XML output of a key when
     117             :  * it is being represented in a context that defines the parent key name.
     118             :  * For example:
     119             :  *
     120             :  * @verbatim
     121             :         <keyset parent="user/sw">
     122             :                 <key basename="kdbedit"..../>
     123             :                 <key basename="phototools"..../>
     124             :                 <key basename="myapp"..../>
     125             :         </keyset>@endverbatim
     126             :  *
     127             :  * In the above example, each @p @<key@> entry was generated by a call to
     128             :  * keyToStreamBasename() having @c "user/sw" as @p parent .
     129             :  *
     130             :  * This method is used when ksToStream() is called with
     131             :  * KDBOption::KDB_O_HIER option.
     132             :  *
     133             :  * @param key the key object to work with
     134             :  * @param stream the FILE where to send the stream
     135             :  * @param parentSize the maximum size of @p parent that will be used.
     136             :  *        If 0, the entire @p parent will be used.
     137             :  * @param parent the string (or part of it, defined by @p parentSize ) that
     138             :  *        will be used to strip from the key name.
     139             :  * @param options Some #option_t ORed:
     140             :  * - @p option_t::KDB_O_NUMBERS \n
     141             :  *   Do not convert UID and GID into user and group names
     142             :  * - @p option_t::KDB_O_CONDENSED \n
     143             :  *   Less human readable, more condensed output
     144             :  * - @p option_t::KDB_O_FULLNAME \n
     145             :  *   The @p user keys are exported with their full names (including
     146             :  *   user domains)
     147             :  *
     148             :  * @return number of bytes written to output
     149             :  */
     150           0 : ssize_t keyToStreamBasename (const Key * key, FILE * stream, const char * parent, const size_t parentSize, option_t options)
     151             : {
     152           0 :         ssize_t written = 0;
     153             : 
     154             :         /* Write key name */
     155           0 :         if (parent)
     156             :         {
     157             :                 /* some logic to see if we should print only the relative basename */
     158             :                 int found;
     159           0 :                 size_t skip = parentSize ? parentSize : elektraStrLen (parent) - 1;
     160             : 
     161           0 :                 found = memcmp (parent, key->key, skip);
     162           0 :                 if (found == 0)
     163             :                 {
     164           0 :                         while (*(key->key + skip) == KDB_PATH_SEPARATOR)
     165           0 :                                 ++skip;
     166             : 
     167           0 :                         if (*(key->key + skip) != 0) /* we don't want a null basename */
     168           0 :                                 written += fprintf (stream, "<key basename=\"%s\"", key->key + skip);
     169             :                 }
     170             :         }
     171             : 
     172           0 :         if (written == 0)
     173             :         { /* no "<key basename=..." was written so far */
     174           0 :                 if (options & KDB_O_FULLNAME)
     175             :                 {
     176             :                         char buffer[KDB_MAX_PATH_LENGTH];
     177           0 :                         keyGetFullName (key, buffer, sizeof (buffer));
     178           0 :                         written += fprintf (stream, "<key name=\"%s\"", buffer);
     179             :                 }
     180             :                 else
     181           0 :                         written += fprintf (stream, "<key name=\"%s\"", key->key);
     182             :         }
     183             : 
     184             : 
     185             :         /* Key type
     186             :         TODO: xml schema does not output type
     187             :         if (options & KDB_O_NUMBERS) {
     188             :                 written+=fprintf(stream," type=\"%d\"", key->type);
     189             :         } else {
     190             :                 buffer[0]=0;
     191             : 
     192             :                 if (key->type & KEY_TYPE_DIR) written+=fprintf(stream, " isdir=\"yes\"");
     193             :                 if (key->type & KEY_TYPE_REMOVE) written+=fprintf(stream, " isremove=\"yes\"");
     194             :                 if (key->type & KEY_TYPE_BINARY) written+=fprintf(stream, " isbinary=\"yes\"");
     195             :         }
     196             :         */
     197             : 
     198           0 :         if (keyGetUID (key) != (uid_t) -1) written += fprintf (stream, " uid=\"%d\"", (int) keyGetUID (key));
     199           0 :         if (keyGetGID (key) != (gid_t) -1) written += fprintf (stream, " gid=\"%d\"", (int) keyGetGID (key));
     200             : 
     201           0 :         if (keyGetMode (key) != KDB_FILE_MODE)
     202             :         {
     203           0 :                 written += fprintf (stream, " mode=\"0%o\"", keyGetMode (key));
     204             :         }
     205             : 
     206             : 
     207           0 :         if (!key->data.v && !keyComment (key))
     208             :         { /* no data AND no comment */
     209           0 :                 written += fprintf (stream, "/>");
     210           0 :                 if (!(options & KDB_O_CONDENSED)) written += fprintf (stream, "\n\n");
     211             : 
     212             :                 return written; /* end of <key/> */
     213             :         }
     214             :         else
     215             :         {
     216           0 :                 if (key->data.v)
     217             :                 {
     218           0 :                         if ((key->dataSize <= 16) && keyIsString (key) && /*TODO: is this for string?*/
     219           0 :                             !strchr (key->data.c, '\n'))
     220             :                         {
     221             : 
     222             :                                 /* we'll use a "value" attribute instead of a <value> node,
     223             :                                    for readability, so the cut size will be 16, which is
     224             :                                    the maximum size of an IPv4 address */
     225             : 
     226           0 :                                 if (options & KDB_O_CONDENSED)
     227           0 :                                         written += fprintf (stream, " ");
     228             :                                 else
     229           0 :                                         written += fprintf (stream, "\n\t");
     230             : 
     231           0 :                                 written += fprintf (stream, "value=\"%s\"", key->data.c);
     232             : 
     233           0 :                                 if (keyComment (key))
     234           0 :                                         written += fprintf (stream, ">\n");
     235             :                                 else
     236             :                                 {
     237           0 :                                         written += fprintf (stream, "/>");
     238           0 :                                         if (!(options & KDB_O_CONDENSED)) written += fprintf (stream, "\n");
     239             : 
     240             :                                         return written;
     241             :                                 }
     242             :                         }
     243             :                         else
     244             :                         { /* value is bigger than 16 bytes: deserves own <value> */
     245           0 :                                 written += fprintf (stream, ">");
     246           0 :                                 if (!(options & KDB_O_CONDENSED)) written += fprintf (stream, "\n\n     ");
     247             : 
     248           0 :                                 written += fprintf (stream, "<value>");
     249           0 :                                 if (keyIsString (key))
     250             :                                 { /*TODO: is this for string?*/
     251           0 :                                         written += fprintf (stream, "<![CDATA[");
     252           0 :                                         fflush (stream);
     253             :                                         /* must chop ending \\0 */
     254           0 :                                         written += fwrite (key->data.v, sizeof (char), key->dataSize - 1, stream);
     255           0 :                                         written += fprintf (stream, "]]>");
     256             :                                 }
     257             :                                 else
     258             :                                 {
     259             :                                         /* TODO Binary values
     260             :                                         char *encoded=elektraMalloc(3*key->dataSize);
     261             :                                         size_t encodedSize;
     262             : 
     263             :                                         written+=fprintf(stream,"\n");
     264             :                                         encodedSize=kdbbEncode(key->data.c,key->dataSize,encoded);
     265             :                                         fflush(stream);
     266             :                                         written+=fwrite(encoded,sizeof(char),encodedSize,stream);
     267             :                                         elektraFree (encoded);
     268             :                                         written+=fprintf(stream,"\n");
     269             :                                         */
     270             :                                 }
     271             :                                 /* fflush(stream); */
     272           0 :                                 written += fprintf (stream, "</value>");
     273             :                         }
     274             :                 }
     275             :                 else
     276             :                 { /* we have no data */
     277           0 :                         if (keyComment (key))
     278             :                         {
     279           0 :                                 written += fprintf (stream, ">");
     280           0 :                                 if (!(options & KDB_O_CONDENSED)) written += fprintf (stream, "\n");
     281             :                         }
     282             :                         else
     283             :                         {
     284           0 :                                 written += fprintf (stream, "/>");
     285           0 :                                 if (!(options & KDB_O_CONDENSED)) written += fprintf (stream, "\n\n");
     286             : 
     287             :                                 return written;
     288             :                         }
     289             :                 }
     290             :         }
     291             : 
     292           0 :         if (!(options & KDB_O_CONDENSED))
     293             :         {
     294           0 :                 written += fprintf (stream, "\n");
     295           0 :                 if (keyComment (key)) written += fprintf (stream, "     ");
     296             :         }
     297             : 
     298           0 :         if (keyComment (key))
     299             :         {
     300           0 :                 written += fprintf (stream, "<comment><![CDATA[%s]]></comment>", keyComment (key));
     301           0 :                 if (!(options & KDB_O_CONDENSED)) written += fprintf (stream, "\n");
     302             :         }
     303             : 
     304           0 :         written += fprintf (stream, "</key>");
     305             : 
     306           0 :         if (!(options & KDB_O_CONDENSED)) written += fprintf (stream, "\n\n");
     307             : 
     308             :         return written;
     309             : }
     310             : 
     311             : /**
     312             :  * Writes to @p stream an XML version of the @p ks object.
     313             :  *
     314             :  * String generated is of the form:
     315             :  * @verbatim
     316             : <keyset>
     317             : <key name=...>...</key>
     318             : <key name=...>...</key>
     319             : <key name=...>...</key>
     320             : 
     321             : </keyset>
     322             :  * @endverbatim
     323             :  *
     324             :  * or if KDB_O_HIER is used, the form will be:
     325             :  * @verbatim
     326             : <keyset parent="user/smallest/parent/name">
     327             : 
     328             : <key basename=...>...</key>
     329             : <key name=...>...</key> <!-- a key thats not under this keyset's parent -->
     330             : <key basename=...>...</key>
     331             : 
     332             : </keyset>
     333             :  * @endverbatim
     334             :  *
     335             :  * KDB_O_HEADER will additionally generate a header like:
     336             :  * @verbatim
     337             : <?xml version="1.0" encoding="UTF-8"?>
     338             : <!-- Generated by Elektra API. Total of n keys. -->
     339             : <keyset xmlns="https://www.libelektra.org"
     340             :         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     341             :         xsi:schemaLocation="https://www.libelektra.org elektra.xsd">
     342             :  * @endverbatim
     343             :  *
     344             :  * @param ks the KeySet to serialise
     345             :  * @param stream where to write output: a file or stdout
     346             :  * @param options accepted #option_t ORed:
     347             :  * - @p option_t::KDB_O_NUMBERS \n
     348             :  *   Do not convert UID and GID into user and group names.
     349             :  * - @p option_t::KDB_O_FULLNAME \n
     350             :  *   The @c user keys are exported with their full names (including
     351             :  *   user domains)
     352             :  * - @p option_t::KDB_O_CONDENSED \n
     353             :  *   Less human readable, more condensed output.
     354             :  * - @p option_t::KDB_O_XMLHEADERS \n
     355             :  *   Exclude the correct XML headers in the output. If not used, the
     356             :  *   &lt;?xml?&gt; and schema info inside the &lt;keyset&gt; object will not be generated.
     357             :  * - @p option_t::KDB_O_HIER \n
     358             :  *   Will generate a &lt;keyset&gt; node containing a @c parent attribute, and
     359             :  *   &lt;key&gt; nodes with a @c basename relative to that @c parent. The @c parent
     360             :  *   is calculated by taking the smallest key name in the keyset, so it is a
     361             :  *   good idea to have only related keys on the keyset. Otherwise, a valid
     362             :  *   consistent XML document still will be generated with regular absolute
     363             :  *   @c name attribute for the &lt;key&gt; nodes, due to a
     364             :  *   clever keyToStreamBasename() implementation.
     365             :  *
     366             :  * @see keyToStream()
     367             :  * @see commandList() for usage example
     368             :  * @return number of bytes written to output, or -1 if some error occurs
     369             :  * @param ks The keyset to output
     370             :  * @param stream the file pointer where to send the stream
     371             :  * @param options see above text
     372             :  */
     373           0 : ssize_t ksToStream (const KeySet * ks, FILE * stream, option_t options)
     374             : {
     375           0 :         size_t written = 0;
     376           0 :         Key * key = 0;
     377           0 :         KeySet * cks = ksDup (ks);
     378             : 
     379           0 :         ksRewind (cks);
     380             : 
     381           0 :         if (options & KDB_O_HEADER)
     382             :         {
     383           0 :                 written += fprintf (stream, "<?xml version=\"1.0\" encoding=\"%s\"?>", "UTF-8");
     384           0 :                 if (~options & KDB_O_CONDENSED)
     385           0 :                         written += fprintf (stream, "\n<!-- Generated by Elektra API. Total of %d keys. -->\n", (int) cks->size);
     386           0 :                 if (~options & KDB_O_CONDENSED)
     387           0 :                         written += fprintf (stream,
     388             :                                             "<keyset xmlns=\"https://www.libelektra.org\"\n"
     389             :                                             "\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
     390             :                                             "\txsi:schemaLocation=\"https://www.libelektra.org elektra.xsd\"\n");
     391             :                 else
     392           0 :                         written += fprintf (stream,
     393             :                                             "<keyset xmlns=\"https://www.libelektra.org\""
     394             :                                             " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
     395             :                                             " xsi:schemaLocation=\"https://www.libelektra.org elektra.xsd\"");
     396             :         }
     397             :         else
     398           0 :                 written += fprintf (stream, "<keyset");
     399             : 
     400           0 :         if (options & KDB_O_HIER)
     401             :         {
     402             :                 char commonParent[KDB_MAX_PATH_LENGTH];
     403             : 
     404           0 :                 ksGetCommonParentName (cks, commonParent, sizeof (commonParent));
     405             : 
     406           0 :                 if (commonParent[0])
     407             :                 {
     408           0 :                         written += fprintf (stream, "        parent=\"%s\">\n", commonParent);
     409           0 :                         ksRewind (cks);
     410           0 :                         while ((key = ksNext (cks)) != 0)
     411           0 :                                 written += keyToStreamBasename (key, stream, commonParent, 0, options);
     412             :                 }
     413             :                 else
     414             :                 {
     415           0 :                         written += fprintf (stream, ">\n");
     416           0 :                         ksRewind (cks);
     417           0 :                         while ((key = ksNext (cks)) != 0)
     418           0 :                                 written += keyToStream (key, stream, options);
     419             :                 }
     420             :         }
     421             :         else
     422             :         { /* No KDB_O_HIER*/
     423           0 :                 written += fprintf (stream, ">\n");
     424           0 :                 ksRewind (cks);
     425           0 :                 while ((key = ksNext (cks)) != 0)
     426           0 :                         written += keyToStream (key, stream, options);
     427             :         }
     428             : 
     429           0 :         written += fprintf (stream, "</keyset>\n");
     430           0 :         ksDel (cks);
     431           0 :         return written;
     432             : }
     433             : 
     434             : /**
     435             :  * Output every information of a single key depending on options.
     436             :  *
     437             :  * The format is not very strict and only intend to be read
     438             :  * by human eyes for debugging purposes. Don't rely on the
     439             :  * format in your applications.
     440             :  *
     441             :  * @param k the key object to work with
     442             :  * @param stream the file pointer where to send the stream
     443             :  * @param options see text above
     444             :  * @see ksOutput()
     445             :  * @retval 1 on success
     446             :  * @retval -1 on allocation errors
     447             :  * @ingroup stream
     448             :  */
     449           0 : int keyOutput (const Key * k, FILE * stream, option_t options)
     450             : {
     451             :         time_t t;
     452             :         size_t s;
     453             :         char * tmc;
     454             : 
     455             :         size_t c;
     456             : 
     457             :         size_t n;
     458             : 
     459           0 :         n = keyGetNameSize (k);
     460           0 :         if (n > 1)
     461             :         {
     462           0 :                 char * nam = (char *) elektraMalloc (n);
     463           0 :                 if (nam == NULL) return -1;
     464           0 :                 keyGetName (k, nam, n);
     465             : 
     466           0 :                 fprintf (stream, "Name[%d]: %s : ", (int) n, nam);
     467             : 
     468           0 :                 elektraFree (nam);
     469             :         }
     470             : 
     471           0 :         s = keyGetValueSize (k);
     472           0 :         if (options & KEY_VALUE && s > 1)
     473             :         {
     474           0 :                 char * str = (char *) elektraMalloc (s);
     475           0 :                 if (str == NULL) return -1;
     476           0 :                 if (keyIsBinary (k))
     477             :                 {
     478             :                         /*
     479             :                         char * bin;
     480             :                         bin = (char*) elektraMalloc (s*3+1);
     481             :                         keyGetBinary(k, str, s);
     482             :                         kdbbEncode (str, s, bin);
     483             :                         elektraFree (bin);
     484             :                         */
     485           0 :                         keyGetBinary (k, str, s);
     486           0 :                         fprintf (stream, "Binary[%d]: %s : ", (int) s, str);
     487             :                 }
     488             :                 else
     489             :                 {
     490           0 :                         keyGetString (k, str, s);
     491           0 :                         fprintf (stream, "String[%d]: %s : ", (int) s, str);
     492             :                 }
     493             : 
     494           0 :                 elektraFree (str);
     495             :         }
     496             : 
     497           0 :         c = keyGetCommentSize (k);
     498           0 :         if (options & KEY_COMMENT && c > 1)
     499             :         {
     500           0 :                 char * com = (char *) elektraMalloc (c);
     501           0 :                 if (com == NULL) return -1;
     502           0 :                 keyGetComment (k, com, c);
     503             : 
     504           0 :                 fprintf (stream, "Comment[%d]: %s : ", (int) c, com);
     505             : 
     506           0 :                 elektraFree (com);
     507             :         }
     508             : 
     509             : 
     510           0 :         if (options & KDB_O_SHOWMETA) fprintf (stream, " : ");
     511           0 :         if (options & KEY_UID) fprintf (stream, "UID: %d : ", (int) keyGetUID (k));
     512           0 :         if (options & KEY_GID) fprintf (stream, "GID: %d : ", (int) keyGetGID (k));
     513           0 :         if (options & KEY_MODE) fprintf (stream, "Mode: %o : ", (int) keyGetMode (k));
     514             : 
     515           0 :         if (options & KEY_ATIME)
     516             :         {
     517           0 :                 t = keyGetATime (k);
     518           0 :                 tmc = ctime (&t);
     519           0 :                 tmc[24] = '\0';
     520           0 :                 fprintf (stream, "ATime: %s : ", tmc);
     521             :         }
     522             : 
     523           0 :         if (options & KEY_MTIME)
     524             :         {
     525           0 :                 t = keyGetMTime (k);
     526           0 :                 tmc = ctime (&t);
     527           0 :                 tmc[24] = '\0';
     528           0 :                 fprintf (stream, "MTime: %s : ", tmc);
     529             :         }
     530             : 
     531           0 :         if (options & KEY_CTIME)
     532             :         {
     533           0 :                 t = keyGetCTime (k);
     534           0 :                 tmc = ctime (&t);
     535           0 :                 tmc[24] = '\0';
     536           0 :                 fprintf (stream, "CTime: %s : ", tmc);
     537             :         }
     538             : 
     539           0 :         if (options & KDB_O_SHOWFLAGS)
     540             :         {
     541           0 :                 if (!(options & KDB_O_SHOWMETA)) fprintf (stream, " ");
     542           0 :                 fprintf (stream, "Flags: ");
     543           0 :                 if (keyIsBinary (k)) fprintf (stream, "b");
     544           0 :                 if (keyIsString (k)) fprintf (stream, "s");
     545           0 :                 if (keyIsInactive (k)) fprintf (stream, "i");
     546           0 :                 if (keyNeedSync (k)) fprintf (stream, "s");
     547             :         }
     548             : 
     549           0 :         fprintf (stream, "\n");
     550           0 :         return 1;
     551             : }
     552             : 
     553             : 
     554             : /**
     555             :  * Output all information of a keyset.
     556             :  *
     557             :  * The format is not very strict and only intend to be read
     558             :  * by human eyes for debugging purposes. Don't rely on the
     559             :  * format in your applications.
     560             :  *
     561             :  * Keys are printed line per line with keyOutput().
     562             :  *
     563             :  * The same options as keyOutput() are taken and passed
     564             :  * to them.
     565             :  *
     566             :  * Additional KDB_O_HEADER will print the number of keys
     567             :  * as first line.
     568             :  *
     569             :  * @param ks the keyset to work with
     570             :  * @param stream the file pointer where to send the stream
     571             :  * @param options
     572             :  * @see keyOutput()
     573             :  * @retval 1 on success
     574             :  * @retval -1 on allocation errors
     575             :  * @ingroup stream
     576             :  */
     577           0 : int ksOutput (const KeySet * ks, FILE * stream, option_t options)
     578             : {
     579             :         Key * key;
     580           0 :         KeySet * cks = ksDup (ks);
     581           0 :         size_t size = 0;
     582             : 
     583           0 :         ksRewind (cks);
     584             : 
     585           0 :         if (KDB_O_HEADER & options)
     586             :         {
     587           0 :                 fprintf (stream, "Output keyset of size %d\n", (int) ksGetSize (cks));
     588             :         }
     589           0 :         while ((key = ksNext (cks)) != NULL)
     590             :         {
     591           0 :                 if (options & KDB_O_SHOWINDICES) fprintf (stream, "[%d] ", (int) size);
     592           0 :                 keyOutput (key, stream, options);
     593           0 :                 size++;
     594             :         }
     595             : 
     596           0 :         ksDel (cks);
     597           0 :         return 1;
     598             : }

Generated by: LCOV version 1.13