static void test_enumdispatcher (void) { printf ("test_enumdispatcher\n"); Key * parentKey = keyNew ("user/tests/regexdispatcher", KEY_END); KeySet * conf = ksNew (0, KS_END); PLUGIN_OPEN ("regexdispatcher"); KeySet * ks = ksNew (1, KS_END); Key * key1 = keyNew ("/key1", KEY_META, "check/enum/#1", "a", KEY_META, "check/enum/#2", "b", KEY_END); Key * key2 = keyNew ("/key2", KEY_META, "check/enum/#1", "a", KEY_META, "check/enum/#2", "b", KEY_META, "check/enum/multi", ",", KEY_END); ksAppendKey (ks, key1); ksAppendKey (ks, key2); succeed_if (plugin->kdbSet (plugin, ks, parentKey) == ELEKTRA_PLUGIN_STATUS_SUCCESS, "call to kdbSet was not successful"); const Key * pKey1 = ksLookupByName (ks, "/key1", KDB_O_NONE); const Key * checkEnum1 = keyGetMeta (pKey1, "check/validation"); succeed_if (checkEnum1, "the single enum regex hasn't been generated"); succeed_if (0 == strcmp (keyString (checkEnum1), "a|b"), "the single enum regex is invalid"); const Key * pKey2 = ksLookupByName (ks, "/key2", KDB_O_NONE); const Key * checkEnum2 = keyGetMeta (pKey2, "check/validation"); succeed_if (checkEnum2, "the multi enum regex hasn't been generated"); succeed_if (0 == strcmp (keyString (checkEnum2), "(a,b)|(b,a)"), "the mutli enum regex is invalid"); keyDel (parentKey); ksDel (ks); PLUGIN_CLOSE (); }
static void test_timeoutConnect (void) { printf ("test connect timeout\n"); Key * parentKey = keyNew ("system/tests/foo", KEY_END); Key * toAdd = keyNew ("system/tests/foo/bar", KEY_END); KeySet * ks = ksNew (0, KS_END); KeySet * conf = ksNew (3, keyNew ("/endpoint", KEY_VALUE, TEST_ENDPOINT, KEY_END), keyNew ("/connectTimeout", KEY_VALUE, TESTCONFIG_CONNECT_TIMEOUT, KEY_END), keyNew ("/subscribeTimeout", KEY_VALUE, TESTCONFIG_SUBSCRIBE_TIMEOUT, KEY_END), KS_END); PLUGIN_OPEN ("zeromqsend"); // initial get to save current state plugin->kdbGet (plugin, ks, parentKey); // add key to keyset ksAppendKey (ks, toAdd); plugin->kdbSet (plugin, ks, parentKey); char * expectedWarningNumber = elektraFormat ("%d", ELEKTRA_WARNING_ZEROMQSEND_TIMEOUT); succeed_if (keyGetMeta (parentKey, "warnings"), "warning meta key was not set"); succeed_if_same_string (expectedWarningNumber, keyValue (keyGetMeta (parentKey, "warnings/#00/number"))); ksDel (ks); keyDel (parentKey); PLUGIN_CLOSE (); elektraFree (expectedWarningNumber); }
KeySet * elektraMetaArrayToKS (Key * key, const char * metaName) { const Key * meta = keyGetMeta (key, metaName); if (!meta) return NULL; KeySet * result = ksNew (0, KS_END); if (keyString (meta)[0] != '#') { ksAppendKey (result, (Key *)meta); ksRewind (result); return result; } ksAppendKey (result, keyDup (meta)); Key * currentKey = keyDup (meta); keyAddName (currentKey, "#"); elektraArrayIncName (currentKey); Key * curMeta = NULL; while ((curMeta = (Key *)keyGetMeta (key, keyName (currentKey))) != NULL) { ksAppendKey (result, keyDup (curMeta)); elektraArrayIncName (currentKey); } keyDel (currentKey); ksRewind (result); return result; }
void test_differentMetaNames (void) { Key * parentKey = keyNew ("user/tests/keytometa", KEY_END); KeySet * conf = ksNew (0, KS_END); PLUGIN_OPEN ("keytometa"); KeySet * ks = createDifferentMetaNameTestKeys (); succeed_if (plugin->kdbGet (plugin, ks, parentKey) >= 1, "call to kdbGet was not successful"); succeed_if (output_error (parentKey), "error in kdbGet"); succeed_if (output_warnings (parentKey), "warnings in kdbGet"); Key * key = ksLookupByName (ks, "user/normalkey1", 0); succeed_if (key, "normalkey1 was removed"); const Key * metaKey1 = keyGetMeta (key, "testmeta1"); succeed_if (metaKey1, "normalkey1 contained no meta testmeta1"); const char * expected1 = "meta line1"; succeed_if (!strcmp (keyString (metaKey1), expected1), "metakey testmeta1 of normalkey1 contained incorrect data"); const Key * metaKey2 = keyGetMeta (key, "testmeta2"); succeed_if (metaKey2, "normalkey1 contained no meta testmeta1"); const char * expected2 = "meta line2"; succeed_if (!strcmp (keyString (metaKey2), expected2), "metakey testmeta1 of normalkey1 contained incorrect data"); keyDel (parentKey); ksDel (ks); PLUGIN_CLOSE (); }
void test_appendSameLevel (void) { Key * parentKey = keyNew ("user/tests/keytometa", KEY_END); KeySet * conf = ksNew (0, KS_END); PLUGIN_OPEN ("keytometa"); KeySet * ks = createSameLevelTestKeys (); succeed_if (plugin->kdbGet (plugin, ks, parentKey) >= 1, "call to kdbGet was not successful"); succeed_if (output_error (parentKey), "error in kdbGet"); succeed_if (output_warnings (parentKey), "warnings in kdbGet"); /* convertkey1 should be converted to childkey1 as childkey1 is on the same level as requested */ Key * childKey = ksLookupByName (ks, "user/levelkey1/childkey1", 0); succeed_if (childKey, "childkey1 was removed"); const Key * metaKey1 = keyGetMeta (childKey, "testmeta"); succeed_if (metaKey1, "childkey1 contained no meta testmeta"); const char * expected1 = "convertkey1value"; succeed_if (!strcmp (keyString (metaKey1), expected1), "metakey testmeta of childkey1 contained incorrect data"); /* convertkey2 should be converted to levelkey as the next key in order is not on the same level */ Key * levelkey1 = ksLookupByName (ks, "user/levelkey1", 0); succeed_if (levelkey1, "levelkey1 was removed"); const Key * metaKey2 = keyGetMeta (levelkey1, "testmeta"); succeed_if (metaKey2, "levelkey1 contained no meta testmeta"); const char * expected2 = "convertkey2value"; succeed_if (!strcmp (keyString (metaKey2), expected2), "metakey testmeta of levelkey1 contained incorrect data"); keyDel (parentKey); ksDel (ks); PLUGIN_CLOSE (); }
/** * Compare the order metadata of two keys. * * @return a number less than, equal to or greater than zero if * the order of k1 is found, respectively, to be less than, * to match, or be greater than the order of k2. If one key is * NULL, but the other isn't, the key which is not NULL is considered * to be greater. If both keys are NULL, they are * considered to be equal. If one key does have an order * metadata but the other has not, the key with the metadata * is considered greater. If no key has metadata, * they are considered to be equal. * * @param ka key to compare with * @param kb other key to compare with */ int elektraKeyCmpOrder (const Key * ka, const Key * kb) { if (!ka && !kb) return 0; if (ka && !kb) return 1; if (!ka && kb) return -1; int aorder = -1; int border = -1; const Key * kam = keyGetMeta (ka, "order"); const Key * kbm = keyGetMeta (kb, "order"); if (kam) aorder = atoi (keyString (kam)); if (kbm) border = atoi (keyString (kbm)); if (aorder > 0 && border > 0) return aorder - border; if (aorder < 0 && border < 0) return 0; if (aorder < 0 && border >= 0) return -1; if (aorder >= 0 && border < 0) return 1; /* cannot happen anyway */ return 0; }
void test_namedMatchFlags (void) { Key * parentKey = keyNew ("user/tests/glob", KEY_END); KeySet * conf = ksNew (20, keyNew ("user/glob/#1", KEY_VALUE, "user/tests/glob/*", KEY_META, "testmetakey1", "testvalue1", KEY_END), /* explicitly request pathname matching */ keyNew ("user/glob/#1/flags", KEY_VALUE, "pathname", KEY_END), KS_END); PLUGIN_OPEN ("glob"); KeySet * ks = createKeys (); succeed_if (plugin->kdbSet (plugin, ks, parentKey) >= 1, "call to kdbSet was not successful"); succeed_if (output_error (parentKey), "error in kdbSet"); succeed_if (output_warnings (parentKey), "warnings in kdbSet"); Key * key = ksLookupByName (ks, "user/tests/glob/test1", 0); exit_if_fail (key, "key user/tests/glob/test1 not found"); const Key * metaKey1 = keyGetMeta (key, "testmetakey1"); exit_if_fail (metaKey1, "testmetakey1 not found"); key = ksLookupByName (ks, "user/tests/glob/test3", 0); exit_if_fail (key, "user/tests/glob/test3 not found"); const Key * metaKey2 = keyGetMeta (key, "testmetakey1"); exit_if_fail (metaKey2, "testmetakey1 not found"); key = ksLookupByName (ks, "user/tests/glob/test2/subtest1", 0); exit_if_fail (key, "user/tests/glob/test2/subtest1 not found"); const Key * metaKey3 = keyGetMeta (key, "testmetakey1"); exit_if_fail (!metaKey3, "testmetakey1 was copied to subtest1, but subtest1 should not be matched with pathname flag"); ksDel (ks); keyDel (parentKey); PLUGIN_CLOSE (); }
static int handleOutOfRangeConflict (Key * parentKey, Key * key, Key * specKey, Key * conflictMeta, OnConflict onConflict) { int ret = 0; switch (onConflict) { case ERROR: ELEKTRA_SET_ERRORF (142, parentKey, "%s has invalid number of members: %s. Expected: %s\n", keyName (key), keyString (conflictMeta), keyString (keyGetMeta (specKey, "array"))); ret = -1; break; case WARNING: ELEKTRA_ADD_WARNINGF (143, parentKey, "%s has invalid number of members: %s. Expected: %s\n", keyName (key), keyString (conflictMeta), keyString (keyGetMeta (specKey, "array"))); break; case INFO: { const char * infoString = "%s has invalid number of member: %s. Expected: %s"; const size_t len = elektraStrLen (infoString) + elektraStrLen (keyName (key)) + MAX_CHARS_IN_LONG + keyGetValueSize (keyGetMeta (specKey, "array")) - 2; char * buffer = elektraMalloc (len); snprintf (buffer, len, infoString, keyName (key), keyString (conflictMeta), keyString (keyGetMeta (specKey, "array"))); elektraMetaArrayAdd (key, "logs/spec/info", buffer); elektraFree (buffer); } break; case IGNORE: break; } return ret; }
char * elektraMetaArrayToString (Key * key, const char * metaName, const char * delim) { char * result = NULL; Key * lookupElem = keyDup (keyGetMeta (key, metaName)); keyAddBaseName (lookupElem, "#0"); Key * elem = (Key *)keyGetMeta (key, keyName (lookupElem)); if (elem != NULL) { elektraRealloc ((void **)&result, keyGetValueSize (elem)); snprintf (result, keyGetValueSize (elem), "%s", keyString (elem)); } elektraArrayIncName (lookupElem); elem = (Key *)keyGetMeta (key, keyName (lookupElem)); while (elem != NULL) { elektraRealloc ((void **)&result, elektraStrLen (result) + keyGetValueSize (elem) + 1); // String (incl. +2 times \0) + delimiter + whitespace strcat (result, delim); strcat (result, keyString (elem)); elektraArrayIncName (lookupElem); elem = (Key *)keyGetMeta (key, keyName (lookupElem)); } keyDel (lookupElem); return result; }
/** * Get the key comment. * * @section comment Comments * * A Key comment is description for humans what this key is for. It may be a * textual explanation of valid values, when and why a user or administrator * changed the key or any other text that helps the user or administrator related * to that key. * * Don't depend on a comment in your program. A user is * always allowed to remove or change it in any way he wants to. But you are * allowed or even encouraged to always show the content of the comment * to the user and allow him to change it. * * @param key the key object to work with * @param returnedComment pre-allocated memory to copy the comments to * @param maxSize number of bytes that will fit returnedComment * @return the number of bytes actually copied to @p returnedString, including * final NULL * @retval 1 if the string is empty * @retval -1 on NULL pointer * @retval -1 if maxSize is 0, not enough to store the comment or when larger then SSIZE_MAX * @see keyGetCommentSize(), keySetComment() */ ssize_t keyGetComment (const Key * key, char * returnedComment, size_t maxSize) { const char * comment; size_t commentSize; if (!key) return -1; if (!maxSize) return -1; if (!returnedComment) return -1; if (maxSize > SSIZE_MAX) return -1; comment = keyValue (keyGetMeta (key, "comment")); commentSize = keyGetValueSize (keyGetMeta (key, "comment")); if (!comment) { /*errno=KDB_ERR_NODESC;*/ returnedComment[0] = 0; return 1; } strncpy (returnedComment, comment, maxSize); if (maxSize < commentSize) { /*errno=KDB_ERR_TRUNC;*/ return -1; } return commentSize; }
void test_zeroMatchFlags (void) { Key * parentKey = keyNew ("user/tests/glob", KEY_END); KeySet * conf = ksNew (20, keyNew ("user/glob/#1", KEY_VALUE, "*test1", KEY_META, "testmetakey1", "testvalue1", KEY_END), /* disable default pathname globbing behaviour */ keyNew ("user/glob/#1/flags", KEY_VALUE, "", KEY_END), KS_END); PLUGIN_OPEN ("glob"); KeySet * ks = createKeys (); succeed_if (plugin->kdbSet (plugin, ks, parentKey) >= 1, "call to kdbSet was not successful"); succeed_if (output_error (parentKey), "error in kdbSet"); succeed_if (output_warnings (parentKey), "warnings in kdbSet"); Key * key = ksLookupByName (ks, "user/tests/glob/test1", 0); exit_if_fail (key, "key user/tests/glob/test1 not found"); const Key * metaKey1 = keyGetMeta (key, "testmetakey1"); exit_if_fail (metaKey1, "testmetakey1 not found"); succeed_if (strcmp ("testvalue1", keyValue (metaKey1)) == 0, "value of metakey testmetakey1 not correct"); key = ksLookupByName (ks, "user/tests/glob/test3", 0); exit_if_fail (key, "user/tests/glob/test3 not found"); succeed_if (!keyGetMeta (key, "testmetakey1"), "testmetakey1 copied to wrong key"); key = ksLookupByName (ks, "user/tests/glob/test2/subtest1", 0); exit_if_fail (key, "user/tests/glob/test2/subtest1 not found"); const Key * metaKey2 = keyGetMeta (key, "testmetakey1"); exit_if_fail (metaKey2, "testmetakey1 not found"); succeed_if (strcmp ("testvalue1", keyValue (metaKey2)) == 0, "value of metakey testmetakey1 not correct"); ksDel (ks); keyDel (parentKey); PLUGIN_CLOSE (); }
/* Check for warnings, print and remove. * Note: not all available information will be printed! * Fields for more information are listed in the value from * the Key returned by keyGetMeta(key,"warnings/#XX") where XX * is the Warning number, starting at 00. * Or print all MetaData, by using the loop from removeMetaData (). */ void printWarnings (Key * key) { if (!keyGetMeta (key, "warnings")) return; char * end; size_t warn_count = strtol (keyString (keyGetMeta (key, "warnings")), &end, 10); if (*end) { printf ("strtol error\n"); return; } size_t warn_iter = 0; char buffer[sizeof ("warnings/#00/description") + sizeof (ELEKTRA_STRINGIFY (SIZE_MAX))]; do { snprintf (&buffer[0], sizeof (buffer), "warnings/#%02zu/description", warn_iter); const Key * warnkey = keyGetMeta (key, buffer); printf ("Warning occurred: %s\n", keyString (warnkey)); ++warn_iter; } while (warn_iter <= warn_count); /*remove all warnings*/ removeMetaData (key, "warnings"); }
void test_metaMerging () { Key *parentKey = keyNew ("user/tests/keytometa", KEY_END); KeySet *conf = ksNew(0, KS_END); PLUGIN_OPEN("keytometa"); KeySet* ks = createMergeTestkeys (); succeed_if(plugin->kdbGet (plugin, ks, parentKey) >= 1, "call to kdbGet was not successful"); succeed_if(output_error (parentKey), "error in kdbGet"); succeed_if(output_warnings (parentKey), "warnings in kdbGet"); Key *key = ksLookupByName(ks, "user/normalkey1", 0); succeed_if (key, "normalkey1 was removed"); const Key *metaKey1 = keyGetMeta(key, "testmeta"); succeed_if (metaKey1, "normalkey1 contained no metakey"); const char *expected1 = "meta line 1\nmeta line 2\nmeta line 3"; succeed_if (!strcmp (keyString(metaKey1), expected1), "metakey of normalkey1 contained incorrect data"); key = ksLookupByName(ks, "user/normalkey2", 0); succeed_if (key, "normalkey2 was removed"); const Key *metaKey2 = keyGetMeta(key, "testmeta"); succeed_if (metaKey2, "normalkey2 contained no metakey"); const char *expected2 = "meta line 30\nmeta line 31\nmeta line 32"; succeed_if (!strcmp (keyString(metaKey2), expected2), "metakey of normalkey2 contained incorrect data"); /* change the value of the middle key */ keySetMeta(key, "testmeta", "meta line 30\nchanged meta line\nmeta line 32"); succeed_if(plugin->kdbSet (plugin, ks, parentKey) >= 1, "call to kdbSet was not successful"); succeed_if(output_error (parentKey), "error in kdbSet"); succeed_if(output_warnings (parentKey), "warnings in kdbSet"); key = ksLookupByName(ks, "user/convertkey30", 0); succeed_if (key, "convertkey30 was not restored"); succeed_if (!strcmp (keyString(key), "meta line 30"), "value of convertkey30 was modified"); key = ksLookupByName (ks, "user/convertkey31", 0); succeed_if (key, "convertkey31 was not restored"); succeed_if (!strcmp (keyString(key), "changed meta line"), "meta information was not written back to convertkey31"); key = ksLookupByName (ks, "user/convertkey32", 0); succeed_if (key, "convertkey32 was not restored"); succeed_if (!strcmp (keyString(key), "meta line 32"), "value of convertkey32 was modified"); keyDel (parentKey); ksDel(ks); PLUGIN_CLOSE (); }
static void setSectionNumber(Key *parentKey, Key *key, KeySet *ks) { if (!strcmp(keyBaseName(key), INTERNAL_ROOT_SECTION)) { Key *tmpKey = keyDup(key); keySetMeta(tmpKey, "ini/section", "0"); keySetMeta(key, "ini/section", "0"); keySetString(tmpKey, 0); ksAppendKey(ks, tmpKey); keyDel(tmpKey); return; } Key *lookupKey = keyDup(key); Key *lastKey = keyDup(lookupKey); while (1) { if (!strcmp(keyName(lookupKey), keyName(parentKey))) { if (keyGetMeta(parentKey, "ini/lastSection")) { long previousSection = atol(keyString(keyGetMeta(parentKey, "ini/lastSection"))); ++previousSection; char buffer[21]; //20 digits (long) + \0 snprintf(buffer, sizeof (buffer), "%ld", previousSection); keySetMeta(parentKey, "ini/lastSection", buffer); keySetMeta(key, "ini/section", buffer); } else { keySetMeta(parentKey, "ini/lastSection", "1"); keySetMeta(parentKey, "ini/section", "0"); keySetMeta(key, "ini/section", "1"); } keySetMeta(lastKey, "ini/section", keyString(keyGetMeta(key, "ini/section"))); ksAppendKey(ks, lastKey); break; } if (keyGetMeta(ksLookup(ks, lookupKey, KDB_O_NONE), "ini/section")) { keySetMeta(key, "ini/section", keyString(keyGetMeta(ksLookup(ks, lookupKey, KDB_O_NONE), "ini/section"))); break; } keySetName(lastKey, keyName(lookupKey)); keyAddName(lookupKey, ".."); } keyDel(lookupKey); keyDel(lastKey); }
/** * @internal * * elektraSortTopology helper * ordering function for qsort */ static int topCmpOrder (const void * a, const void * b) { const Key * ka = (*(const Key **)a); const Key * kb = (*(const Key **)b); if (!ka && !kb) return 0; if (ka && !kb) return 1; if (!ka && kb) return -1; const Key * kam = keyGetMeta (ka, "order"); const Key * kbm = keyGetMeta (kb, "order"); return strcmp (keyString (kam), keyString (kbm)); }
/** * Get key full name, including the user domain name. * * @return number of bytes written * @retval 1 on empty name * @retval -1 on NULL pointers * @retval -1 if maxSize is 0 or larger than SSIZE_MAX * @param key the key object * @param returnedName pre-allocated memory to write the key name * @param maxSize maximum number of bytes that will fit in returnedName, including the final NULL * @ingroup keyname */ ssize_t keyGetFullName (const Key * key, char * returnedName, size_t maxSize) { size_t userSize = sizeof ("user") - 1; size_t ownerSize; ssize_t length; ssize_t maxSSize; char * cursor; if (!key) return -1; if (!returnedName) return -1; if (!maxSize) return -1; if (maxSize > SSIZE_MAX) return -1; maxSSize = maxSize; length = keyGetFullNameSize (key); if (length == 1) { /*errno=KDB_ERR_NOKEY;*/ returnedName[0] = 0; return length; } else if (length < 0) return length; else if (length > maxSSize) { /* errno=KDB_ERR_TRUNC; */ return -1; } cursor = returnedName; if (keyIsUser (key)) { strncpy (cursor, key->key, userSize); cursor += userSize; if (keyGetMeta (key, "owner")) { *cursor = ':'; ++cursor; ownerSize = keyGetValueSize (keyGetMeta (key, "owner")) - 1; strncpy (cursor, keyValue (keyGetMeta (key, "owner")), ownerSize); cursor += ownerSize; } strcpy (cursor, key->key + userSize); } else strcpy (cursor, key->key); return length; }
void test_type() { Key *key; succeed_if (key = keyNew(0), "could not create a new key"); succeed_if (keyValue(keyGetMeta(key, "binary")) == 0, "wrong type after key creation"); succeed_if (keySetString (key, "mystring") == sizeof("mystring"), "could not set string"); succeed_if (keyValue(keyGetMeta(key, "binary")) == 0, "wrong type after setting string"); succeed_if (keySetBinary (key, "mystring", sizeof("mystring")) == sizeof("mystring"), "could not set binary"); succeed_if (keyValue(keyGetMeta(key, "binary")) != 0, "wrong type after setting string"); keyDel (key); }
void test_onlyFirstMatchIsApplied (void) { Key * parentKey = keyNew ("user/tests/glob", KEY_END); // clang-format off KeySet * conf = ksNew (20, keyNew ("user/glob/#1", KEY_VALUE, "user/tests/glob/test1*", KEY_META, "testmetakey1", "testvalue1", KEY_END), keyNew ("user/glob/#2", KEY_VALUE, "user/tests/glob/*", KEY_META, "testmetakey2", "testvalue2", KEY_END), /* disable all flags */ keyNew ("user/glob/#1/flags", KEY_VALUE, "", KEY_END), keyNew ("user/glob/#2/flags", KEY_VALUE, "", KEY_END), KS_END); // clang-format on PLUGIN_OPEN ("glob"); KeySet * ks = createKeys (); succeed_if (plugin->kdbGet (plugin, ks, parentKey) >= 1, "call to kdbSet was not successful"); succeed_if (output_error (parentKey), "error in kdbSet"); succeed_if (output_warnings (parentKey), "warnings in kdbSet"); Key * key = ksLookupByName (ks, "user/tests/glob/test1", 0); exit_if_fail (key, "key user/tests/glob/test1 not found"); const Key * firstMatchKey = keyGetMeta (key, "testmetakey1"); exit_if_fail (firstMatchKey, "testmetakey1 not found"); const Key * secondMatchKey = keyGetMeta (key, "testmetakey2"); exit_if_fail (!secondMatchKey, "testmetakey2 was applied to testmetakey1 although another match was already applied") key = ksLookupByName (ks, "user/tests/glob/test2/subtest1", 0); exit_if_fail (key, "user/tests/glob/test2/subtest1 not found"); exit_if_fail (keyGetMeta (key, "testmetakey2"), "testmetakey2 not found"); key = ksLookupByName (ks, "user/tests/glob/test3", 0); exit_if_fail (key, "user/tests/glob/test3 not found"); exit_if_fail (keyGetMeta (key, "testmetakey2"), "testmetakey2 not found"); ksDel (ks); keyDel (parentKey); PLUGIN_CLOSE (); }
void test_simpleAppendModes() { Key *parentKey = keyNew ("user/tests/keytometa", KEY_END); KeySet *conf = ksNew(0, KS_END); PLUGIN_OPEN("keytometa"); KeySet *ks = createSimpleTestKeys (); succeed_if(plugin->kdbGet (plugin, ks, parentKey) >= 1, "call to kdbGet was not successful"); succeed_if(output_error (parentKey), "error in kdbGet"); succeed_if(output_warnings (parentKey), "warnings in kdbGet"); /* converted keys must be removed from the result */ succeed_if (!ksLookupByName(ks, "user/convertkey1", 0), "convertkey1 was not converted"); succeed_if (!ksLookupByName(ks, "user/convertkey2", 0), "convertkey2 was not converted"); /* normalkey2 must contain meta information generated from convertkey1 (via next) */ Key *key = ksLookupByName(ks, "user/normalkey2", 0); succeed_if (key, "normalkey2 was removed"); const Key *metaKey1 = keyGetMeta(key, "testmeta"); succeed_if (metaKey1, "normalkey2 contained no metakey"); succeed_if (!strcmp (keyString(metaKey1), "testvalue1"), "metakey of normalkey2 contained incorrect data"); /* normalkey3 must contain meta information generated from convertkey2 (via previous) */ key = ksLookupByName (ks, "user/normalkey3", 0); succeed_if (key, "normalkey3 was removed"); const Key *metaKey2 = keyGetMeta(key, "testmeta"); succeed_if (metaKey2, "normalkey3 contained no metakey"); succeed_if (!strcmp (keyString(metaKey2), "testvalue2"), "metakey of normalkey3 contained incorrect data"); /* normalkey1 must contain meta information generated from subkey (via parent) */ key = ksLookupByName (ks, "user/normalkey1", 0); succeed_if (key, "normalkey1 was removed"); const Key *metaKey3 = keyGetMeta(key, "testmeta"); succeed_if (metaKey3, "normalkey1 contained no metakey"); succeed_if (!strcmp (keyString(metaKey3), "testvalue3"), "metakey of normalkey1 contained incorrect data"); keyDel (parentKey); ksDel(ks); PLUGIN_CLOSE () ; }
static void test_defaultdispatcher (void) { printf ("test_defaultdispatcher\n"); Key * parentKey = keyNew ("user/tests/regexdispatcher", KEY_END); KeySet * conf = ksNew (0, KS_END); PLUGIN_OPEN ("regexdispatcher"); KeySet * ks = ksNew (1, KS_END); Key * key = keyNew ("/key", KEY_META, "default", ".\\+*?[^]$(){}=!<>|:-asfdjklö123", KEY_END); ksAppendKey (ks, key); succeed_if (plugin->kdbSet (plugin, ks, parentKey) == ELEKTRA_PLUGIN_STATUS_SUCCESS, "call to kdbSet was not successful"); const Key * pKey = ksLookupByName (ks, "/key", KDB_O_NONE); const Key * defaultValue = keyGetMeta (pKey, "defaultValue"); succeed_if (defaultValue, "the default value regex hasn't been generated"); succeed_if (0 == strcmp (keyString (defaultValue), "\\.\\\\\\+\\*\\?\\[\\^\\]\\$\\(\\)\\{\\}\\=\\!\\<\\>\\|\\:\\-asfdjklö123"), "the default value regex is invalid"); keyDel (parentKey); ksDel (ks); PLUGIN_CLOSE (); }
/** * Reads the type metadata of a given array element. * * @param elektra An Elektra instance. * @param name The name of the array. * @param index The index of the array element whose type information shall be read. * @return the KDBType of the key */ KDBType elektraGetArrayElementType (Elektra * elektra, const char * keyname, size_t index) { elektraSetLookupKey (elektra, keyname); const Key * key = elektraFindArrayElementKey (elektra, keyname, index, NULL); const Key * metaKey = keyGetMeta (key, "type"); return metaKey == NULL ? NULL : keyString (metaKey); }
static int basicUse (int argc, const char ** argv) { Key * parentKey = keyNew ("/sw/org/example/#0/current", KEY_END); //! [basic use] KDB * kdb = kdbOpen (parentKey); KeySet * ks = ksNew (0, KS_END); kdbGet (kdb, ks, parentKey); int result = elektraGetOpts (ks, argc, argv, (const char **) environ, parentKey); if (result == -1) { fprintf (stderr, "ERROR: %s\n", keyString (keyGetMeta (parentKey, "error/reason"))); keyDel (parentKey); ksDel (ks); return EXIT_FAILURE; } if (result == 1) { char * help = elektraGetOptsHelpMessage (parentKey, NULL, NULL); fprintf (stderr, "%s\n", help); elektraFree (help); keyDel (parentKey); ksDel (ks); return EXIT_SUCCESS; } //! [basic use] ksDel (ks); kdbClose (kdb, parentKey); keyDel (parentKey); return EXIT_SUCCESS; }
/** * Get the group ID of a key. * * @deprecated This API is obsolete. * * @section GID GID * * The group ID is a unique identification for every group present on * a system. Keys will belong to root (0) as long as you did not get their * real GID with kdbGet(). * * Unlike UID users might change their group. This makes it possible to * share configuration between some users. * * A fresh key will have (gid_t)-1 also known as the group nogroup. * It means that the key is not related to a group ID at the moment. * * @param key the key object to work with * @return the system's GID of the key * @retval (gid_t)-1 on NULL key or currently unknown ID * @see keySetGID(), keyGetUID() */ gid_t keyGetGID (const Key * key) { const char * gid; long int val; char * endptr; int errorval = errno; if (!key) return (gid_t)-1; gid = keyValue (keyGetMeta (key, "gid")); if (!gid) return (gid_t)-1; if (*gid == '\0') return (gid_t)-1; /*From now on we have to leave using cleanup*/ errno = 0; val = strtol (gid, &endptr, 10); /*Check for errors*/ if (errno) goto cleanup; /*Check if nothing was found*/ if (endptr == gid) goto cleanup; /*Check if the whole string was processed*/ if (*endptr != '\0') goto cleanup; return val; cleanup: /*First restore errno*/ errno = errorval; return (gid_t)-1; }
static void validateWildcardSubs (KeySet * ks, Key * key, Key * specKey) { const Key * requiredMeta = keyGetMeta (specKey, "required"); if (!requiredMeta) return; Key * tmpParent = keyDup (key); keySetBaseName (tmpParent, 0); Key * parent = ksLookup (ks, tmpParent, KDB_O_NONE); keyDel (tmpParent); if (parent == NULL) return; KeySet * ksCopy = ksDup (ks); KeySet * subKeys = ksCut (ksCopy, parent); Key * cur; long subCount = 0; while ((cur = ksNext (subKeys)) != NULL) { if (keyIsDirectBelow (parent, cur)) ++subCount; } long required = atol (keyString (requiredMeta)); if (required != subCount) { char buffer[MAX_CHARS_IN_LONG + 1]; snprintf (buffer, sizeof (buffer), "%ld", subCount); keySetMeta (parent, "conflict/invalid/subcount", buffer); } ksDel (subKeys); ksDel (ksCopy); }
/** * Return the key mode permissions. * * @deprecated This API is obsolete. * * Default is 0664 (octal) for keys and 0775 for directory keys * which used keySetDir(). * * The defaults are defined with the macros KDB_FILE_MODE and KDB_DIR_MODE. * * For more information about the mode permissions see @ref mode. * * @param key the key object to work with * @return mode permissions of the key * @retval KDB_FILE_MODE as defaults * @retval (mode_t)-1 on NULL pointer * @see keySetMode() */ mode_t keyGetMode (const Key * key) { const char * mode; long int val; char * endptr; int errorval = errno; if (!key) return (mode_t)-1; mode = keyValue (keyGetMeta (key, "mode")); if (!mode) return KDB_FILE_MODE; if (*mode == '\0') return KDB_FILE_MODE; /*From now on we have to leave using cleanup*/ errno = 0; val = strtol (mode, &endptr, 8); /*Check for errors*/ if (errno) goto cleanup; /*Check if nothing was found*/ if (endptr == mode) goto cleanup; /*Check if the whole string was processed*/ if (*endptr != '\0') goto cleanup; return val; cleanup: /*First restore errno*/ errno = errorval; return KDB_FILE_MODE; }
static void validateArrayRange (Key * parent, long validCount, Key * specKey) { const Key * arrayRange = keyGetMeta (specKey, "array"); if (arrayRange != NULL) { char * rangeString = elektraMalloc (keyGetValueSize (arrayRange)); keyGetString (arrayRange, rangeString, keyGetValueSize (arrayRange)); char * delimPtr = strchr (rangeString, '-'); long min = 0; long max = 0; if (delimPtr) { char * maxString = delimPtr + 1; *delimPtr = '\0'; char * minString = rangeString; min = atoi (minString); max = atoi (maxString); } else { min = max = atoi (rangeString); } if (validCount < min || validCount > max) { char buffer[MAX_CHARS_IN_LONG + 1]; snprintf (buffer, sizeof (buffer), "%ld", validCount); keySetMeta (parent, "conflict/range", buffer); } elektraFree (rangeString); } }
static void test_plainIniEmptyWrite (char * fileName) { Key * parentKey = keyNew ("user/tests/ini-write", KEY_VALUE, elektraFilename (), KEY_END); KeySet * conf = ksNew (0, KS_END); PLUGIN_OPEN ("ini"); KeySet * ks = ksNew (30, keyNew ("user/tests/ini-write/nosectionkey", KEY_VALUE, "nosectionvalue", KEY_END), keyNew ("user/tests/ini-write/section1", KEY_BINARY, KEY_END), keyNew ("user/tests/ini-write/section1/key1", KEY_VALUE, "value1", KEY_END), keyNew ("user/tests/ini-write/section1/key2", KEY_VALUE, "value2", KEY_END), keyNew ("user/tests/ini-write/section2", KEY_BINARY, KEY_END), keyNew ("user/tests/ini-write/section2/key3", KEY_VALUE, "value3", KEY_END), keyNew ("user/tests/ini-write/section2/emptykey", KEY_META, "ini/empty", "", KEY_END), KS_END); succeed_if (plugin->kdbSet (plugin, ks, parentKey) >= 1, "call to kdbSet was not successful"); succeed_if (output_error (parentKey), "error in kdbSet"); succeed_if (output_warnings (parentKey), "warnings in kdbSet"); succeed_if (compare_line_files (srcdir_file (fileName), keyString (parentKey)), "files do not match as expected"); KeySet * readKS = ksNew (0, KS_END); succeed_if (plugin->kdbGet (plugin, readKS, parentKey) >= 0, "kdbGet failed"); const Key * meta; Key * searchKey = keyNew ("user/tests/ini-write/section2/emptykey", KEY_META, "ini/empty", "", KEY_END); Key * key = ksLookup (readKS, searchKey, KDB_O_NONE); meta = keyGetMeta (key, "ini/empty"); succeed_if (meta != NULL, "reading empty key again failed"); ksDel (readKS); keyDel (parentKey); keyDel (searchKey); ksDel (ks); PLUGIN_CLOSE (); }
static void applyGlob (KeySet * returned, KeySet * glob) { Key * cur; ksRewind (returned); while ((cur = ksNext (returned)) != 0) { Key * match; ksRewind (glob); while ((match = ksNext (glob)) != 0) { const Key * flagKey = keyGetMeta (match, "glob/flags"); int matchApplied; if (flagKey) { matchApplied = elektraGlobMatch (cur, match, keyString (flagKey)); } else { /* if no flags were provided, default to FNM_PATHNAME behaviour */ matchApplied = elektraGlobMatch (cur, match, "pathname"); } if (matchApplied) break; } } }
/** * Get last time the key metadata was changed from disk. * * @deprecated This API is obsolete. * * You will get 0 when the key was not read already. * * Any changed field in metadata will influence the * ctime of a key. * * This time is not updated if only value * or comment are changed. * * Not changed keys will not update this time, * even after kdbSet(). * * It is possible that other keys written to disc * influence this time if the backend is not grained * enough. * * @param key Key to get information from. * @see keySetCTime() * @retval (time_t)-1 on NULL pointer * @return the metadata change time */ time_t keyGetCTime (const Key * key) { const char * ctime; long int val; char * endptr; int errorval = errno; if (!key) return (time_t)-1; ctime = keyValue (keyGetMeta (key, "ctime")); if (!ctime) return 0; if (*ctime == '\0') return (time_t)-1; /*From now on we have to leave using cleanup*/ errno = 0; val = strtol (ctime, &endptr, 10); /*Check for errors*/ if (errno) goto cleanup; /*Check if nothing was found*/ if (endptr == ctime) goto cleanup; /*Check if the whole string was processed*/ if (*endptr != '\0') goto cleanup; return val; cleanup: /*First restore errno*/ errno = errorval; return (time_t)-1; }
static void test_rangedispatcher (void) { printf ("test_rangedispatcher\n"); Key * parentKey = keyNew ("user/tests/regexdispatcher", KEY_END); KeySet * conf = ksNew (0, KS_END); PLUGIN_OPEN ("regexdispatcher"); KeySet * ks = ksNew (1, KS_END); Key * key1 = keyNew ("/key1", KEY_META, "check/range", "0-5000", KEY_END); ksAppendKey (ks, key1); succeed_if (plugin->kdbSet (plugin, ks, parentKey) == ELEKTRA_PLUGIN_STATUS_SUCCESS, "call to kdbSet was not successful"); const Key * pKey1 = ksLookupByName (ks, "/key1", KDB_O_NONE); const Key * checkRange1 = keyGetMeta (pKey1, "check/validation"); succeed_if (checkRange1, "the range regex hasn't been generated"); succeed_if (0 == strcmp (keyString (checkRange1), "[0-9]|[1-9][0-9]|[1-9][0-9][0-9]|[1-4][0-9][0-9][0-9]|5000"), "the range regex is invalid"); keyDel (parentKey); ksDel (ks); PLUGIN_CLOSE (); }