LCOV - code coverage report
Current view: top level - src/libs/elektra - key.c (source / functions) Hit Total Coverage
Test: coverage-filtered.info Lines: 87 96 90.6 %
Date: 2019-09-12 12:28:41 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /**
       2             :  * @file
       3             :  *
       4             :  * @brief Methods for Key manipulation.
       5             :  *
       6             :  * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
       7             :  */
       8             : 
       9             : 
      10             : #ifdef HAVE_KDBCONFIG_H
      11             : #include "kdbconfig.h"
      12             : #endif
      13             : 
      14             : #if DEBUG && defined(HAVE_STDIO_H)
      15             : #include <stdio.h>
      16             : #endif
      17             : 
      18             : #ifdef HAVE_STDARG_H
      19             : #include <stdarg.h>
      20             : #endif
      21             : 
      22             : #ifdef HAVE_STRING_H
      23             : #include <string.h>
      24             : #endif
      25             : 
      26             : #ifdef HAVE_STDLIB_H
      27             : #include <stdlib.h>
      28             : #endif
      29             : 
      30             : #include "kdb.h"
      31             : #include "kdbprivate.h"
      32             : 
      33             : 
      34             : /**
      35             :  * @defgroup key Key
      36             :  *
      37             :  * @brief Key is an essential class that encapsulates key @link keyname name @endlink,
      38             :  * @link keyvalue value @endlink and @link keymeta metainfo @endlink.
      39             :  *
      40             :  * To use it include:
      41             :  * @code
      42             : #include <kdb.h>
      43             :  * @endcode
      44             :  *
      45             :  * Key properties are:
      46             :  * - @link keyname Key name @endlink
      47             :  * - @link keyvalue Key value @endlink
      48             :  * - @link keymeta Key metadata @endlink, including but not limited to:
      49             :  *   - @link keyGetComment() Key comment @endlink
      50             :  *   - @link keyGetOwner() Key owner @endlink
      51             :  *   - @link keymeta UID, GID and filesystem-like mode permissions @endlink
      52             :  *   - @link keymeta Mode, change and modification times @endlink
      53             :  *
      54             :  * @par ABI
      55             :  * Due to ABI compatibility, the @p Key structure is not defined in kdb.h,
      56             :  * only declared. So you can only declare @p pointers to @p Keys in your
      57             :  * program, and allocate and free memory for them with keyNew()
      58             :  * and keyDel() respectively.
      59             :  *
      60             :  *
      61             :  * @par Reference Counting
      62             :  * Every key has its reference counter (see keyGetRef() for longer
      63             :  * explanation) that will be initialized
      64             :  * with 0, that means a subsequent call of keyDel() will delete
      65             :  * the key. If you append the key to a keyset the reference counter
      66             :  * will be incremented by one (see keyIncRef()) and the key can't be
      67             :  * deleted by a keyDel().
      68             :  *
      69             :  * @par
      70             :  * As you can imagine this refcounting allows you to put the Key in your
      71             :  * own data structures.
      72             :  * It can be a very powerful feature, e.g. if you need your own-defined
      73             :  * ordering or different Models of your configuration.
      74             :  */
      75             : 
      76             : 
      77             : /*
      78             :  * @internal
      79             :  *
      80             :  * Allocates and initializes a key
      81             :  * @returns 0 if allocation did not work, the key otherwise
      82             :  */
      83     9617082 : static Key * elektraKeyMalloc (void)
      84             : {
      85     9617082 :         Key * key = (Key *) elektraMalloc (sizeof (Key));
      86     9617082 :         if (!key) return 0;
      87     9617082 :         keyInit (key);
      88             : 
      89     9617082 :         return key;
      90             : }
      91             : 
      92             : 
      93             : /**
      94             :  * A practical way to fully create a Key object in one step.
      95             :  *
      96             :  * To just get a key object, simple do:
      97             :  *
      98             :  * @snippet keyNew.c Simple
      99             :  *
     100             :  * keyNew() allocates memory for a key object and keyDel() cleans
     101             :  * everything up.
     102             :  *
     103             :  * We can also give an empty key name and a KEY_END tag with the same
     104             :  * effect as before:
     105             :  *
     106             :  * @snippet keyNew.c Alternative
     107             :  *
     108             :  * But we can also give the key a proper name right from the start:
     109             :  *
     110             :  * @snippet keyNew.c With Name
     111             :  *
     112             :  * If you want the key object to contain a name, value, comment and other
     113             :  * meta info read on.
     114             :  *
     115             :  * @note When you already have a key with similar properties its
     116             :  * easier to keyDup() the key.
     117             :  *
     118             :  * You can call keyNew() in many different ways depending on the attribute tags you
     119             :  * pass as parameters. Tags are represented as #keyswitch_t values, and
     120             :  * tell keyNew() which Key attribute comes next.
     121             :  * The Key attribute tags are the following:
     122             :  * - ::KEY_VALUE \n
     123             :  *   Next parameter is a pointer to the value that will be used.
     124             :  *   If no ::KEY_BINARY was used before, a string is assumed.
     125             :  *   @snippet keyNew.c With Value
     126             :  * - ::KEY_SIZE \n
     127             :  *   Define a maximum length of the value. This is only used when setting
     128             :  *   a binary key.
     129             :  *   @snippet keyNew.c With Size
     130             :  * - ::KEY_META \n
     131             :  *   Next two parameter is a metaname and a metavalue. See keySetMeta().
     132             :  *   @snippet keyNew.c With Meta
     133             :  * - ::KEY_END \n
     134             :  *   Must be the last parameter passed to keyNew(). It is always
     135             :  *   required, unless the @p keyName is 0.
     136             :  * - ::KEY_FLAGS \n
     137             :  *   Bitwise disjunction of flags, which don't require one or more values.
     138             :  *   recommended way to set multiple flags. overrides previously defined flags.
     139             :  *   @snippet keyNew.c With Flags
     140             :  * - ::KEY_BINARY \n
     141             :  *   Allows one to change the key to a binary key.
     142             :  *   Make sure that you also pass ::KEY_SIZE before you set the value.
     143             :  *   Otherwise it will be cut off with first \\0 in the string.
     144             :  *   So this flag toggle from keySetString() to keySetBinary().
     145             :  *   If no value (nor size) is given, it will be a NULL key.
     146             :  *   @snippet keyNew.c With Binary
     147             :  * - ::KEY_CASCADING_NAME allow the name to start with /
     148             :  *   useful for ksLookup() and kdbGet() parent/lookup keys
     149             :  * - ::KEY_META_NAME allow the name to start with arbitrary namespaces
     150             :  *   useful to compare with metakeys
     151             :  *
     152             :  *
     153             :  *
     154             :  * @deprecated The flags below are deprecated and ::KEY_META should be
     155             :  * preferred. They remain some time, however, for compatibility:
     156             :  * - ::KEY_DIR \n
     157             :  *   Define that the key is a directory rather than an ordinary key.
     158             :  *   This means its executable bits in its mode are set.
     159             :  *   But even without this option the key can have subkeys.
     160             :  *   See keySetDir().
     161             :  * - ::KEY_OWNER \n
     162             :  *   Next parameter is the owner. See keySetOwner().
     163             :  * - ::KEY_UID, ::KEY_GID \n
     164             :  *   Next parameter is taken as the UID (uid_t) or GID (gid_t) that will
     165             :  *   be defined on the key.
     166             :  *   See keySetUID() and keySetGID().
     167             :  * - ::KEY_MODE \n
     168             :  *   Next parameter is taken as mode permissions (int) to the key.
     169             :  *   See keySetMode().
     170             :  *   @snippet keyNew.c With Mode
     171             :  * - ::KEY_COMMENT \n
     172             :  *   Next parameter is a comment. See keySetComment().
     173             :  *   @snippet keyNew.c With Everything
     174             :  *
     175             :  *
     176             :  *
     177             :  * @param name a valid name to the key, or NULL to get a simple
     178             :  *      initialized, but really empty, object
     179             :  * @see keyDel()
     180             :  * @return a pointer to a new allocated and initialized Key object.
     181             :  * @retval NULL on allocation error or if an invalid @p name was passed (see keySetName()).
     182             :  * @ingroup key
     183             :  *
     184             :  */
     185     8277291 : Key * keyNew (const char * name, ...)
     186             : {
     187             :         Key * k;
     188             : 
     189     8277291 :         if (!name)
     190             :         {
     191     6260777 :                 k = elektraKeyMalloc ();
     192             :         }
     193             :         else
     194             :         {
     195             :                 va_list va;
     196     2016514 :                 va_start (va, name);
     197     2016514 :                 k = keyVNew (name, va);
     198     2016514 :                 va_end (va);
     199             :         }
     200             : 
     201     8277291 :         return k;
     202             : }
     203             : 
     204             : 
     205             : /**
     206             :  * @copydoc keyNew
     207             :  *
     208             :  * @pre caller must use va_start and va_end on va
     209             :  * @param va the variadic argument list
     210             :  */
     211     2213958 : Key * keyVNew (const char * name, va_list va)
     212             : {
     213     2213958 :         Key * key = elektraKeyMalloc ();
     214     2213958 :         if (!key) return 0;
     215     2213958 :         keyVInit (key, name, va);
     216     2213958 :         return key;
     217             : }
     218             : 
     219             : /**
     220             :  * Return a duplicate of a key.
     221             :  *
     222             :  * Memory will be allocated as needed for dynamic properties.
     223             :  *
     224             :  * The new key will not be member of any KeySet and
     225             :  * will start with a new reference counter at 0. A
     226             :  * subsequent keyDel() will delete the key.
     227             :  *
     228             :  * @code
     229             : int f (const Key * source)
     230             : {
     231             :         Key * dup = keyDup (source);
     232             :         // work with duplicate
     233             :         keyDel (dup);
     234             :         // everything related to dup is freed
     235             :         // and source is unchanged
     236             : }
     237             :  * @endcode
     238             :  *
     239             :  * Like for a new key after keyNew() a subsequent ksAppend()
     240             :  * makes a KeySet to take care of the lifecycle of the key.
     241             :  *
     242             :  * @code
     243             : int g (const Key * source, KeySet * ks)
     244             : {
     245             :         Key * dup = keyDup (source);
     246             :         // work with duplicate
     247             :         ksAppendKey (ks, dup);
     248             :         // ksDel(ks) will also free the duplicate
     249             :         // source remains unchanged.
     250             : }
     251             :  * @endcode
     252             :  *
     253             :  * Duplication of keys should be preferred to keyNew(),
     254             :  * because data like owner can be filled with a copy
     255             :  * of the key instead of asking the environment.
     256             :  * It can also be optimized in the checks, because the keyname
     257             :  * is known to be valid.
     258             :  *
     259             :  * @param source has to be an initialized source Key
     260             :  * @retval 0 failure or on NULL pointer
     261             :  * @return a fully copy of source on success
     262             :  * @see ksAppend(), keyDel(), keyNew()
     263             :  * @ingroup key
     264             :  */
     265     1142735 : Key * keyDup (const Key * source)
     266             : {
     267     1142735 :         Key * dest = 0;
     268             : 
     269     1142735 :         if (!source) return 0;
     270             : 
     271     1142347 :         dest = elektraKeyMalloc ();
     272     1142347 :         if (!dest) return 0;
     273             : 
     274             :         /* Copy the struct data */
     275     1142347 :         *dest = *source;
     276             : 
     277             :         /* get rid of properties bound to old key */
     278     1142347 :         dest->ksReference = 0;
     279     1142347 :         dest->flags = KEY_FLAG_SYNC;
     280             : 
     281             :         /* prepare to set dynamic properties */
     282     1142347 :         dest->key = dest->data.v = dest->meta = 0;
     283             : 
     284             :         /* copy dynamic properties */
     285     1142347 :         if (keyCopy (dest, source) == -1)
     286             :         {
     287           0 :                 keyDel (dest);
     288           0 :                 return 0;
     289             :         }
     290             : 
     291             :         return dest;
     292             : }
     293             : 
     294             : 
     295             : /**
     296             :  * Copy or Clear a key.
     297             :  *
     298             :  * Most often you may prefer keyDup() which allocates
     299             :  * a new key and returns a duplication of another key.
     300             :  *
     301             :  * But when you need to copy into an existing key, e.g.
     302             :  * because it was passed by a pointer in a function
     303             :  * you can do so:
     304             :  *
     305             :  * @snippet keyCopy.c Basic Usage
     306             :  *
     307             :  * The reference counter will not be changed for
     308             :  * both keys. Affiliation to keysets
     309             :  * are also not affected.
     310             :  *
     311             :  * The metadata will be duplicated for the destination
     312             :  * key. So it will not take much additional space, even
     313             :  * with lots of metadata.
     314             :  *
     315             :  * When you pass a NULL-pointer as source the
     316             :  * data of dest will be cleaned completely
     317             :  * (except reference counter, see keyClear()) and
     318             :  * you get a fresh dest key:
     319             :  *
     320             :  * @snippet keyCopy.c Clear
     321             :  *
     322             :  * If you want to copy everything, except e.g. the value
     323             :  * you can use keyCopy() too:
     324             :  *
     325             :  * @snippet keyCopy.c Copy Without Value
     326             :  *
     327             :  * Restrain from coping everything yourself, because it will lead to
     328             :  * wrong metadata and is not able to copy empty or cascading names:
     329             :  *
     330             :  * @snippet keyCopy.c Individual Copy
     331             :  *
     332             :  *
     333             :  * @param dest the key which will be written to
     334             :  * @param source the key which should be copied
     335             :  *     or NULL to clean the destination key
     336             :  * @ingroup key
     337             :  * @retval -1 on failure when a NULL pointer
     338             :  *     was passed for dest or a dynamic property could not
     339             :  *     be written. The content will be unmodified then.
     340             :  * @retval 0 when dest was cleaned
     341             :  * @retval 1 when source was successfully copied
     342             :  * @see keyDup() to get a duplication of a key
     343             :  */
     344     1142422 : int keyCopy (Key * dest, const Key * source)
     345             : {
     346     1142422 :         if (!dest) return -1;
     347             : 
     348     1142422 :         if (test_bit (dest->flags, KEY_FLAG_RO_NAME) || test_bit (dest->flags, KEY_FLAG_RO_VALUE) ||
     349             :             test_bit (dest->flags, KEY_FLAG_RO_META))
     350             :         {
     351             :                 return -1;
     352             :         }
     353             : 
     354     1142420 :         if (!source)
     355             :         {
     356          12 :                 keyClear (dest);
     357          12 :                 return 0;
     358             :         }
     359             : 
     360             :         // remember dynamic memory to be removed
     361     1142408 :         char * destKey = dest->key;
     362     1142408 :         void * destData = dest->data.c;
     363     1142408 :         KeySet * destMeta = dest->meta;
     364             : 
     365             :         // duplicate dynamic properties
     366     1142408 :         if (source->key)
     367             :         {
     368     1121995 :                 dest->key = elektraStrNDup (source->key, source->keySize + source->keyUSize);
     369     1121995 :                 if (!dest->key) goto memerror;
     370             :         }
     371             :         else
     372             :         {
     373       20413 :                 dest->key = 0;
     374             :         }
     375             : 
     376     1142408 :         if (source->data.v)
     377             :         {
     378      847880 :                 dest->data.v = elektraStrNDup (source->data.v, source->dataSize);
     379      847880 :                 if (!dest->data.v) goto memerror;
     380             :         }
     381             :         else
     382             :         {
     383      294528 :                 dest->data.v = 0;
     384             :         }
     385             : 
     386     1142408 :         if (source->meta)
     387             :         {
     388      547263 :                 dest->meta = ksDup (source->meta);
     389      547263 :                 if (!dest->meta) goto memerror;
     390             :         }
     391             :         else
     392             :         {
     393      595145 :                 dest->meta = 0;
     394             :         }
     395             : 
     396             :         // successful, now do the irreversible stuff: we obviously modified dest
     397     1142408 :         set_bit (dest->flags, KEY_FLAG_SYNC);
     398             : 
     399             :         // copy sizes accordingly
     400     1142408 :         dest->keySize = source->keySize;
     401     1142408 :         dest->keyUSize = source->keyUSize;
     402     1142408 :         dest->dataSize = source->dataSize;
     403             : 
     404             :         // free old resources of destination
     405     1142408 :         if (!test_bit (dest->flags, KEY_FLAG_MMAP_KEY)) elektraFree (destKey);
     406     1142408 :         if (!test_bit (dest->flags, KEY_FLAG_MMAP_DATA)) elektraFree (destData);
     407     1142408 :         ksDel (destMeta);
     408             : 
     409     1142408 :         return 1;
     410             : 
     411             : memerror:
     412           0 :         elektraFree (dest->key);
     413           0 :         elektraFree (dest->data.v);
     414           0 :         ksDel (dest->meta);
     415             : 
     416           0 :         dest->key = destKey;
     417           0 :         dest->data.v = destData;
     418           0 :         dest->meta = destMeta;
     419           0 :         return -1;
     420             : }
     421             : 
     422             : 
     423             : /**
     424             :  * A destructor for Key objects.
     425             :  *
     426             :  * Every key created by keyNew() must be
     427             :  * deleted with keyDel().
     428             :  *
     429             :  * It is safe to delete keys which are
     430             :  * in a keyset, the number of references
     431             :  * will be returned then.
     432             :  *
     433             :  * It is save to delete a nullpointer,
     434             :  * -1 will be returned then.
     435             :  *
     436             :  * It is also save to delete a multiple
     437             :  * referenced key, nothing will happen
     438             :  * then and the reference counter will
     439             :  * be returned.
     440             :  *
     441             :  * @param key the key object to delete
     442             :  * @see keyNew(), keyIncRef(), keyGetRef()
     443             :  * @return the value of the reference counter
     444             :  *         if the key is within keyset(s)
     445             :  * @retval 0 when the key was freed
     446             :  * @retval -1 on null pointers
     447             :  * @ingroup key
     448             :  *
     449             :  */
     450    21607457 : int keyDel (Key * key)
     451             : {
     452             :         int rc;
     453             : 
     454    21607457 :         if (!key) return -1;
     455             : 
     456    21501366 :         if (key->ksReference > 0)
     457             :         {
     458    11883201 :                 return key->ksReference;
     459             :         }
     460             : 
     461     9618165 :         int keyInMmap = test_bit (key->flags, KEY_FLAG_MMAP_STRUCT);
     462             : 
     463     9618165 :         rc = keyClear (key);
     464             : 
     465     9618165 :         if (!keyInMmap)
     466             :         {
     467     9616727 :                 elektraFree (key);
     468             :         }
     469             : 
     470             :         return rc;
     471             : }
     472             : 
     473             : /**
     474             :  * Key Object Cleaner.
     475             :  *
     476             :  * Will reset all internal data.
     477             :  *
     478             :  * After this call you will receive a fresh
     479             :  * key.
     480             :  *
     481             :  * The reference counter will stay unmodified.
     482             :  *
     483             :  * @note that you might also clear() all aliases
     484             :  * with this operation.
     485             :  *
     486             :  * @code
     487             : int f (Key *k)
     488             : {
     489             :         keyClear (k);
     490             :         // you have a fresh key k here
     491             :         keySetString (k, "value");
     492             :         // the caller will get an empty key k with an value
     493             : }
     494             :  * @endcode
     495             :  *
     496             :  * @retval returns 0 on success
     497             :  * @retval -1 on null pointer
     498             :  *
     499             :  * @param key the key object to work with
     500             :  * @ingroup key
     501             :  */
     502     9618201 : int keyClear (Key * key)
     503             : {
     504     9618201 :         if (!key)
     505             :         {
     506             :                 return -1;
     507             :         }
     508             : 
     509     9618201 :         size_t ref = 0;
     510             : 
     511     9618201 :         ref = key->ksReference;
     512             : 
     513     9618201 :         int keyStructInMmap = test_bit (key->flags, KEY_FLAG_MMAP_STRUCT);
     514             : 
     515     9618201 :         if (key->key && !test_bit (key->flags, KEY_FLAG_MMAP_KEY)) elektraFree (key->key);
     516     9618201 :         if (key->data.v && !test_bit (key->flags, KEY_FLAG_MMAP_DATA)) elektraFree (key->data.v);
     517     9618201 :         if (key->meta) ksDel (key->meta);
     518             : 
     519     9618201 :         keyInit (key);
     520             : 
     521     9618201 :         if (keyStructInMmap) key->flags |= KEY_FLAG_MMAP_STRUCT;
     522             : 
     523             :         /* Set reference properties */
     524     9618201 :         key->ksReference = ref;
     525             : 
     526     9618201 :         return 0;
     527             : }
     528             : 
     529             : 
     530             : /**
     531             :  * Increment the viability of a key object.
     532             :  *
     533             :  * This function is intended for applications
     534             :  * using their own reference counter for
     535             :  * key objects. With it you can increment
     536             :  * the reference and thus avoid destruction
     537             :  * of the object in a subsequent keyDel().
     538             :  *
     539             :  * The reference counter can't be incremented
     540             :  * once it reached SSIZE_MAX. In that situation
     541             :  * nothing will happen and SSIZE_MAX will be
     542             :  * returned.
     543             :  *
     544             :  * @note keyDup() will reset the references for dupped key.
     545             :  *
     546             :  * @return the value of the new reference counter
     547             :  * @retval -1 on null pointer
     548             :  * @retval SSIZE_MAX when maximum exceeded
     549             :  * @param key the key object to work with
     550             :  * @see keyGetRef() for longer explanation, keyDecRef(), keyDel()
     551             :  * @ingroup key
     552             :  */
     553    15665930 : ssize_t keyIncRef (Key * key)
     554             : {
     555    15665930 :         if (!key) return -1;
     556             : 
     557    15323410 :         if (key->ksReference < SSIZE_MAX)
     558    15323410 :                 return ++key->ksReference;
     559             :         else
     560             :                 return SSIZE_MAX;
     561             : }
     562             : 
     563             : 
     564             : /**
     565             :  * Decrement the viability of a key object.
     566             :  *
     567             :  * The references will be decremented for ksPop() or successful calls
     568             :  * of ksLookup() with the option KDB_O_POP.
     569             :  * It will also be decremented with an following keyDel() in
     570             :  * the case that an old key is replaced with another key with
     571             :  * the same name.
     572             :  *
     573             :  * The reference counter can't be decremented
     574             :  * once it reached 0. In that situation
     575             :  * nothing will happen and 0 will be
     576             :  * returned.
     577             :  *
     578             :  * @note keyDup() will reset the references for dupped key.
     579             :  *
     580             :  * @return the value of the new reference counter
     581             :  * @retval -1 on null pointer
     582             :  * @retval 0 when the key is ready to be freed
     583             :  * @param key the key object to work with
     584             :  * @see keyGetRef() for longer explanation, keyDel(), keyIncRef()
     585             :  * @ingroup key
     586             :  */
     587    15535355 : ssize_t keyDecRef (Key * key)
     588             : {
     589    15535355 :         if (!key) return -1;
     590             : 
     591    15519445 :         if (key->ksReference > 0)
     592    15324282 :                 return --key->ksReference;
     593             :         else
     594             :                 return 0;
     595             : }
     596             : 
     597             : 
     598             : /**
     599             :  * Return how many references the key has.
     600             :  *
     601             :  * The reference counting is the essential property of keys to make sure
     602             :  * that they can be put safely into data structures. E.g. if you put
     603             :  * a Key into a KeySet:
     604             :  *
     605             :  * @snippet keyNew.c Ref in KeySet
     606             :  *
     607             :  * You can even add the key to more KeySets:
     608             :  *
     609             :  * @snippet keyNew.c Ref in multiple KeySets
     610             :  *
     611             :  * If you increment only by one with keyIncRef() the same as said above
     612             :  * is valid:
     613             :  *
     614             :  * @snippet keyNew.c Ref
     615             :  *
     616             :  * or use keyIncRef() more than once:
     617             :  *
     618             :  * @snippet keyNew.c Multi Ref
     619             :  *
     620             :  * The key won't be deleted by a keyDel() as long refcounter is not 0.
     621             :  *
     622             :  * The references will be incremented on successful calls to
     623             :  * ksAppendKey() or ksAppend().
     624             :  *
     625             :  * @note keyDup() will reset the references for dupped key.
     626             :  *
     627             :  * For your own applications you can use
     628             :  * keyIncRef() and keyDecRef() for reference
     629             :  * counting, too.
     630             :  *
     631             :  * @param key the key object to work with
     632             :  * @return the number of references
     633             :  * @retval -1 on null pointer
     634             :  * @see keyIncRef() and keyDecRef()
     635             :  * @ingroup key
     636             :  **/
     637         385 : ssize_t keyGetRef (const Key * key)
     638             : {
     639         385 :         if (!key) return -1;
     640             : 
     641         385 :         return key->ksReference;
     642             : }

Generated by: LCOV version 1.13