int elektraTracerGet (Plugin * handle, KeySet * returned, Key * parentKey) { ssize_t nr_keys = 0; Key * k = 0; if (!strcmp (keyName (parentKey), "system/elektra/modules/tracer")) { KeySet * info = ksNew (50, keyNew ("system/elektra/modules/tracer", KEY_VALUE, "tracer plugin waits for your orders", KEY_END), keyNew ("system/elektra/modules/tracer/exports", KEY_END), keyNew ("system/elektra/modules/tracer/exports/open", KEY_FUNC, elektraTracerOpen, KEY_END), keyNew ("system/elektra/modules/tracer/exports/close", KEY_FUNC, elektraTracerClose, KEY_END), keyNew ("system/elektra/modules/tracer/exports/get", KEY_FUNC, elektraTracerGet, KEY_END), keyNew ("system/elektra/modules/tracer/exports/set", KEY_FUNC, elektraTracerSet, KEY_END), keyNew ("system/elektra/modules/tracer/exports/error", KEY_FUNC, elektraTracerError, KEY_END), #include "readme_tracer.c" keyNew ("system/elektra/modules/tracer/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END); ksAppend (returned, info); ksDel (info); return 1; } printf ("tracer: get(%p, %s, %s): ", (void *) handle, keyName (parentKey), keyString (parentKey)); while ((k = ksNext (returned)) != 0) { printf ("%s ", keyName (k)); ++nr_keys; } printf ("%zd\n", nr_keys); return nr_keys; }
static void test_ksAppend (const size_t storagePlugin, const char * tmpFile) { Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END); open_storage_plugin (storagePlugin); Plugin * plugin = plugins[storagePlugin]; KeySet * ks = simpleTestKeySet (); succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "kdbSet was not successful"); succeed_if (plugin->kdbGet (plugin, ks, parentKey) == 1, "kdbGet was not successful"); KeySet * toAppend = ksNew (10, keyNew ("user/tests/storage/zzzz", KEY_VALUE, "root key", KEY_END), keyNew ("user/tests/storage/simpleKey/c", KEY_VALUE, "c value", KEY_END), keyNew ("user/tests/storage/simpleKey/d", KEY_VALUE, "d value", KEY_END), KS_END); if (ksAppend (ks, toAppend) == -1) { yield_error ("ksAppend failed"); } succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "kdbSet was not successful"); ksDel (ks); ks = ksNew (0, KS_END); succeed_if (plugin->kdbGet (plugin, ks, parentKey) == 1, "kdbGet was not successful"); ksDel (toAppend); keyDel (parentKey); ksDel (ks); closeStoragePlugin (storagePlugin); }
int elektraDbusGet (Plugin * handle, KeySet * returned, Key * parentKey) { if (!strcmp (keyName (parentKey), "system/elektra/modules/dbus")) { KeySet * contract = ksNew (30, keyNew ("system/elektra/modules/dbus", KEY_VALUE, "dbus plugin waits for your orders", KEY_END), keyNew ("system/elektra/modules/dbus/exports", KEY_END), keyNew ("system/elektra/modules/dbus/exports/get", KEY_FUNC, elektraDbusGet, KEY_END), keyNew ("system/elektra/modules/dbus/exports/set", KEY_FUNC, elektraDbusSet, KEY_END), keyNew ("system/elektra/modules/dbus/exports/close", KEY_FUNC, elektraDbusClose, KEY_END), #include ELEKTRA_README (dbus) keyNew ("system/elektra/modules/dbus/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END); ksAppend (returned, contract); ksDel (contract); return 1; /* success */ } // remember all keys KeySet * ks = (KeySet *)elektraPluginGetData (handle); if (ks) ksDel (ks); elektraPluginSetData (handle, ksDup (returned)); return 1; /* success */ }
static KeySet * prepareGlobalKS (KeySet * ks, Key * parentKey) { ksRewind (ks); Key * cutKey = keyNew ("/", KEY_CASCADING_NAME, KEY_END); keyAddName (cutKey, strchr (keyName (parentKey), '/')); KeySet * cutKS = ksCut (ks, cutKey); Key * specCutKey = keyNew ("spec", KEY_END); KeySet * specCut = ksCut (cutKS, specCutKey); ksRewind (specCut); Key * cur; while ((cur = ksNext (specCut)) != NULL) { if (keyGetNamespace (cur) == KEY_NS_CASCADING) { ksAppendKey (cutKS, cur); keyDel (ksLookup (specCut, cur, KDB_O_POP)); } } ksAppend (ks, specCut); ksDel (specCut); keyDel (specCutKey); keyDel (cutKey); ksRewind (cutKS); return cutKS; }
/** * @internal * Recursively move all keys in keyset below source to dest. * * Modifies the keyset. * * Example: * ``` * moveKeysRecursive("user/plugins/#0", "user/plugins/#1", config); * ``` * * @param source Root part to replace * @param dest Destination for keys * @param keyset keyset */ static void moveKeysRecursive (const char * source, const char * dest, KeySet * keyset) { Key * sourceBaseKey = keyNew (source, KEY_END); KeySet * newKeys = ksNew (0, KS_END); // Rename keys in keyset Key * sourceKey; ksRewind (keyset); while ((sourceKey = ksNext (keyset)) != NULL) { // Rename all keys below sourceKey if (!keyIsBelowOrSame (sourceBaseKey, sourceKey)) continue; Key * destKey = renameKey (source, dest, sourceKey); ksAppendKey (newKeys, destKey); } // Remove source keys from keyset KeySet * cut = ksCut (keyset, sourceBaseKey); ksDel (cut); ksAppend (keyset, newKeys); ksDel (newKeys); keyDel (sourceBaseKey); }
/** * Merges together all parts of split into dest. * * @param split the split object to work with * @param dest the destination keyset where all keysets are appended. * @retval 1 on success * @ingroup split */ int elektraSplitMerge (Split * split, KeySet * dest) { /* Iterate everything */ for (size_t i = 0; i < split->size; ++i) { ksAppend (dest, split->keysets[i]); } return 1; }
/** * Updates registrations with current data from storage. * Part of elektra plugin contract. * * @param handle plugin handle * @param returned key set containing current data from storage * @param parentKey key for errors * * @retval 1 on success * @retval -1 on failure */ int elektraInternalnotificationGet (Plugin * handle, KeySet * returned, Key * parentKey) { if (!elektraStrCmp (keyName (parentKey), "system/elektra/modules/internalnotification")) { KeySet * contract = ksNew ( 30, keyNew ("system/elektra/modules/internalnotification", KEY_VALUE, "internalnotification plugin waits for your orders", KEY_END), keyNew ("system/elektra/modules/internalnotification/exports", KEY_END), keyNew ("system/elektra/modules/internalnotification/exports/get", KEY_FUNC, elektraInternalnotificationGet, KEY_END), keyNew ("system/elektra/modules/internalnotification/exports/set", KEY_FUNC, elektraInternalnotificationSet, KEY_END), keyNew ("system/elektra/modules/internalnotification/exports/open", KEY_FUNC, elektraInternalnotificationOpen, KEY_END), keyNew ("system/elektra/modules/internalnotification/exports/close", KEY_FUNC, elektraInternalnotificationClose, KEY_END), keyNew ("system/elektra/modules/internalnotification/exports/notificationCallback", KEY_FUNC, elektraInternalnotificationDoUpdate, KEY_END), // Export register* functions INTERNALNOTIFICATION_EXPORT_FUNCTION (Int), INTERNALNOTIFICATION_EXPORT_FUNCTION (UnsignedInt), INTERNALNOTIFICATION_EXPORT_FUNCTION (Long), INTERNALNOTIFICATION_EXPORT_FUNCTION (UnsignedLong), INTERNALNOTIFICATION_EXPORT_FUNCTION (LongLong), INTERNALNOTIFICATION_EXPORT_FUNCTION (UnsignedLongLong), INTERNALNOTIFICATION_EXPORT_FUNCTION (Float), INTERNALNOTIFICATION_EXPORT_FUNCTION (Double), // Export register* functions for kdb_*_t types INTERNALNOTIFICATION_EXPORT_FUNCTION (KdbBoolean), INTERNALNOTIFICATION_EXPORT_FUNCTION (KdbChar), INTERNALNOTIFICATION_EXPORT_FUNCTION (KdbOctet), INTERNALNOTIFICATION_EXPORT_FUNCTION (KdbShort), INTERNALNOTIFICATION_EXPORT_FUNCTION (KdbUnsignedShort), INTERNALNOTIFICATION_EXPORT_FUNCTION (KdbLong), INTERNALNOTIFICATION_EXPORT_FUNCTION (KdbUnsignedLong), INTERNALNOTIFICATION_EXPORT_FUNCTION (KdbLongLong), INTERNALNOTIFICATION_EXPORT_FUNCTION (KdbUnsignedLongLong), INTERNALNOTIFICATION_EXPORT_FUNCTION (KdbFloat), INTERNALNOTIFICATION_EXPORT_FUNCTION (KdbDouble), INTERNALNOTIFICATION_EXPORT_FUNCTION (KdbLongDouble), keyNew ("system/elektra/modules/internalnotification/exports/registerCallback", KEY_FUNC, elektraInternalnotificationRegisterCallback, KEY_END), keyNew ("system/elektra/modules/internalnotification/exports/registerCallbackSameOrBelow", KEY_FUNC, elektraInternalnotificationRegisterCallbackSameOrBelow, KEY_END), keyNew ("system/elektra/modules/internalnotification/exports/setConversionErrorCallback", KEY_FUNC, elektraInternalnotificationSetConversionErrorCallback, KEY_END), #include ELEKTRA_README keyNew ("system/elektra/modules/internalnotification/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END); ksAppend (returned, contract); ksDel (contract); return 1; } elektraInternalnotificationUpdateRegisteredKeys (handle, returned); return 1; }
/** * @brief Bootstrap, first phase with fallback * @internal * * @param handle already allocated, but without defaultBackend * @param [out] keys for bootstrapping * @param errorKey key to add errors too * * @retval -1 failure: cannot initialize defaultBackend * @retval 0 warning: could not get initial config * @retval 1 success * @retval 2 success in fallback mode */ int elektraOpenBootstrap (KDB * handle, KeySet * keys, Key * errorKey) { handle->defaultBackend = backendOpenDefault (handle->modules, KDB_DB_INIT, errorKey); if (!handle->defaultBackend) return -1; handle->split = splitNew (); splitAppend (handle->split, handle->defaultBackend, keyNew (KDB_SYSTEM_ELEKTRA, KEY_END), 2); keySetName (errorKey, KDB_SYSTEM_ELEKTRA); keySetString (errorKey, "kdbOpen(): get"); int funret = 1; int ret = kdbGet (handle, keys, errorKey); int fallbackret = 0; if (ret == 0 || ret == -1) { // could not get KDB_DB_INIT, try KDB_DB_FILE // first cleanup: ksClear (keys); backendClose (handle->defaultBackend, errorKey); splitDel (handle->split); // then create new setup: handle->defaultBackend = backendOpenDefault (handle->modules, KDB_DB_FILE, errorKey); if (!handle->defaultBackend) { elektraRemoveMetaData (errorKey, "error"); // fix errors from kdbGet() return -1; } handle->split = splitNew (); splitAppend (handle->split, handle->defaultBackend, keyNew (KDB_SYSTEM_ELEKTRA, KEY_END), 2); keySetName (errorKey, KDB_SYSTEM_ELEKTRA); keySetString (errorKey, "kdbOpen(): get fallback"); fallbackret = kdbGet (handle, keys, errorKey); keySetName (errorKey, "system/elektra/mountpoints"); KeySet * cutKeys = ksCut (keys, errorKey); if (fallbackret == 1 && ksGetSize (cutKeys) != 0) { funret = 2; } ksAppend (keys, cutKeys); ksDel (cutKeys); } if (ret == -1 && fallbackret == -1) { funret = 0; } elektraRemoveMetaData (errorKey, "error"); // fix errors from kdbGet() return funret; }
static KeySet * readFile (Key * parentKey) { FILE * fp = fopen (keyString (parentKey), "r"); KeySet * result = ksNew (0, KS_END); if (!fp) return result; while (!feof (fp)) { KeySet * package = nextPackage (fp, parentKey); ksAppend (result, package); ksDel (package); } return result; }
Command::Command(EditorController *con, KeySet *ks, const char *name) : QObject (con, name), _controller ( con ) { ksRewind ( ks ); ::Key *walker = ksNext ( ks ); _subject = ksNew ( ); while ( walker ) { ::Key *key = keyNew ( walker->key, KEY_SWITCH_END ); keyDup ( walker, key ); ksAppend ( _subject, key ); walker = ksNext ( ks ); } }
int loadConfiguration (Elektra ** elektra, ElektraError ** error) { KeySet * defaults = ksNew (6, keyNew("", KEY_META, "mountpoint", "tests_gen_elektra_context.ini", KEY_END), keyNew ("/mydouble", KEY_VALUE, "0.0", KEY_META, "default", "0.0", KEY_META, "type", "double", KEY_END), keyNew ("/myfloatarray/#", KEY_VALUE, "0.0", KEY_META, "default", "0.0", KEY_META, "type", "float", KEY_END), keyNew ("/myint", KEY_VALUE, "0", KEY_META, "default", "0", KEY_META, "type", "long", KEY_END), keyNew ("/mystring", KEY_META, "default", "", KEY_META, "type", "string", KEY_END), keyNew ("/print", KEY_VALUE, "0", KEY_META, "default", "0", KEY_META, "type", "boolean", KEY_END), KS_END); ; Elektra * e = elektraOpen ("/tests/script/gen/elektra/simple", defaults, error); if (e == NULL) { return -1; } KeySet * contract = ksNew (1, keyNew ("system/plugins/global/gopts", KEY_VALUE, "mounted", KEY_END), KS_END); ; ElektraError * err = NULL; elektraEnsure (e, contract, &err); if (err != NULL) { *error = err; return -1; } helpKey = elektraHelpKey (e); if (helpKey != NULL) { elektraClose (e); return 2; } KeySet * defaultContext = ksNew (0, KS_END); ; ksAppend (elektraContext (e), defaultContext); ksDel (defaultContext); *elektra = e; return 0; }
//! [f] void f (KeySet * iterator, KeySet * lookup) { KeySet * append = ksNew (ksGetSize (lookup), KS_END); Key * key; Key * current; ksRewind (iterator); while ((current = ksNext (iterator))) { key = ksLookup (lookup, current, KDB_O_POP); // do something... ksAppendKey (append, key); // now append it to append, not lookup! keyDel (key); // make sure to ALWAYS delete poped keys. } ksAppend (lookup, append); // now lookup needs to be sorted only once, append never ksDel (append); }
int elektraHexcodeGet (Plugin * handle, KeySet * returned, Key * parentKey) { /* get all keys */ if (!strcmp (keyName (parentKey), "system/elektra/modules/hexcode")) { KeySet * pluginConfig = ksNew (30, keyNew ("system/elektra/modules/hexcode", KEY_VALUE, "hexcode plugin waits for your orders", KEY_END), keyNew ("system/elektra/modules/hexcode/exports", KEY_END), keyNew ("system/elektra/modules/hexcode/exports/get", KEY_FUNC, elektraHexcodeGet, KEY_END), keyNew ("system/elektra/modules/hexcode/exports/set", KEY_FUNC, elektraHexcodeSet, KEY_END), keyNew ("system/elektra/modules/hexcode/exports/open", KEY_FUNC, elektraHexcodeOpen, KEY_END), keyNew ("system/elektra/modules/hexcode/exports/close", KEY_FUNC, elektraHexcodeClose, KEY_END), #include "readme_hexcode.c" keyNew ("system/elektra/modules/hexcode/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END); ksAppend (returned, pluginConfig); ksDel (pluginConfig); return 1; } CHexData * hd = elektraPluginGetData (handle); if (!hd->buf) { hd->buf = elektraMalloc (1000); hd->bufalloc = 1000; } Key * cur; ksRewind (returned); while ((cur = ksNext (returned)) != 0) { size_t valsize = keyGetValueSize (cur); if (valsize > hd->bufalloc) { hd->bufalloc = valsize; hd->buf = realloc (hd->buf, hd->bufalloc); } elektraHexcodeDecode (cur, hd); } return 1; /* success */ }
/**Do a shallow copy of all metadata from source to dest. * * The key dest will additionally have all metadata * the source had. * Meta data not present in source will not be changed. * Meta data which was present in source and dest will * be overwritten. * * For example the metadata type is copied into the * Key k: * * @snippet keyMeta.c Basic Copy All * * The main purpose of this function is for plugins or * applications which want to add the same metadata to * n keys. When you do that with keySetMeta() it will * take n times the memory for the key. This can be * considerable amount of memory for many keys with * some metadata for each. * * To avoid that problem you can use keyCopyAllMeta() * or keyCopyMeta(): * * @snippet keyMeta.c Shared Meta All * * @post for every metaName present in source: keyGetMeta(source, metaName) == keyGetMeta(dest, metaName) * * @retval 1 if was successfully copied * @retval 0 if source did not have any metadata * @retval -1 on null pointer of dest or source * @retval -1 on memory problems * @param dest the destination where the metadata should be copied too * @param source the key where the metadata should be copied from * @ingroup keymeta */ int keyCopyAllMeta (Key * dest, const Key * source) { if (!source) return -1; if (!dest) return -1; if (dest->flags & KEY_FLAG_RO_META) return -1; if (source->meta) { /*Make sure that dest also does not have metaName*/ if (dest->meta) { ksAppend (dest->meta, source->meta); } else { dest->meta = ksDup (source->meta); } return 1; } return 0; }
static void test_complexInsert (char * source, char * compare) { Key * parentKey = keyNew ("user/tests/ini-write", KEY_VALUE, srcdir_file (source), KEY_END); Key * writeParentKey = keyNew ("user/tests/ini-write", KEY_VALUE, elektraFilename (), KEY_END); KeySet * conf = ksNew (0, KS_END); KeySet * ks = ksNew (30, KS_END); KeySet * appendKS = ksNew (10, keyNew ("user/tests/ini-write/section/subsection", KEY_BINARY, KEY_END), keyNew ("user/tests/ini-write/section/subsection/subkey", KEY_VALUE, "subval", KEY_END), keyNew ("user/tests/ini-write/section/zkey3", KEY_VALUE, "3", KEY_END), KS_END); PLUGIN_OPEN ("ini"); succeed_if (plugin->kdbGet (plugin, ks, parentKey) >= 0, "call to kdbGet was not successful"); keyDel (ksLookup (ks, parentKey, KDB_O_POP)); keyDel (parentKey); ksAppend (ks, appendKS); succeed_if (plugin->kdbSet (plugin, ks, writeParentKey) >= 1, "call to kdbSet was not successful"); succeed_if (compare_line_files (srcdir_file (compare), keyString (writeParentKey)), "files do not match as expected"); keyDel (ksLookup (ks, writeParentKey, KDB_O_POP)); keyDel (writeParentKey); ksDel (appendKS); ksDel (ks); PLUGIN_CLOSE (); }
static void test_ksCut (const size_t storagePlugin, const char * tmpFile) { Key * parentKey = keyNew (TEST_ROOT_KEY, KEY_VALUE, tmpFile, KEY_END); open_storage_plugin (storagePlugin); Plugin * plugin = plugins[storagePlugin]; // create keyset with some folder 'other' that we will then cut KeySet * ks = simpleTestKeySet (); KeySet * other = ksNew (10, keyNew ("user/tests/storage/other", KEY_VALUE, "other key", KEY_END), keyNew ("user/tests/storage/other/a", KEY_VALUE, "other a value", KEY_END), keyNew ("user/tests/storage/other/b", KEY_VALUE, "other b value", KEY_END), KS_END); if (ksAppend (ks, other) == -1) { yield_error ("ksAppend failed"); } succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "kdbSet was not successful"); succeed_if (plugin->kdbGet (plugin, ks, parentKey) == 1, "kdbGet was not successful"); // now cut the 'other' folder Key * cutKey = keyNew ("user/tests/storage/other", KEY_END); KeySet * returned = ksCut (ks, cutKey); succeed_if (returned, "keyset is empty (does not contain the cut keyset)"); KeySet * simple = simpleTestKeySet (); compare_keyset (simple, ks); compare_keyset (other, returned); ksDel (other); ksDel (returned); ksDel (simple); keyDel (cutKey); keyDel (parentKey); ksDel (ks); closeStoragePlugin (storagePlugin); }
static KeySet * convertKeys (Key ** keyArray, size_t numKeys, KeySet * orig) { Key * current = 0; Key * prevAppendTarget = 0; KeySet * prevConverted = ksNew (0, KS_END); KeySet * nextConverted = ksNew (0, KS_END); KeySet * result = ksNew (0, KS_END); for (size_t index = 0; index < numKeys; index++) { current = keyArray[index]; if (!keyGetMeta (current, CONVERT_METANAME)) { /* flush out "previous" and "next" keys which may have been collected * because the current key serves as a new border */ ksAppend (result, prevConverted); flushConvertedKeys (prevAppendTarget, prevConverted, orig); prevAppendTarget = current; ksAppend (result, nextConverted); flushConvertedKeys (current, nextConverted, orig); continue; } const char * appendMode = getAppendMode (current); const char * metaName = keyString (keyGetMeta (current, CONVERT_METANAME)); Key * bufferKey = 0; if (!strcmp (appendMode, "previous")) { ksAppendKey (prevConverted, current); } if (!strcmp (appendMode, "next")) { ksAppendKey (nextConverted, current); } if (!strcmp (appendMode, "parent")) { Key * parent = findNearestParent (current, orig); elektraKeyAppendMetaLine (parent, metaName, keyString (current)); ksAppendKey (result, current); removeKeyFromResult (current, parent, orig); } if (bufferKey) { keySetString (bufferKey, keyName (current)); } } ksAppend (result, prevConverted); flushConvertedKeys (prevAppendTarget, prevConverted, orig); ksAppend (result, nextConverted); flushConvertedKeys (0, nextConverted, orig); ksDel (nextConverted); ksDel (prevConverted); return result; }
int elektraIconvGet (Plugin * handle, KeySet * returned, Key * parentKey) { Key * cur; ksRewind (returned); if (!strcmp (keyName (parentKey), "system/elektra/modules/iconv")) { KeySet * pluginConfig = ksNew (30, keyNew ("system/elektra/modules/iconv", KEY_VALUE, "iconv plugin waits for your orders", KEY_END), keyNew ("system/elektra/modules/iconv/exports", KEY_END), keyNew ("system/elektra/modules/iconv/exports/get", KEY_FUNC, elektraIconvGet, KEY_END), keyNew ("system/elektra/modules/iconv/exports/set", KEY_FUNC, elektraIconvSet, KEY_END), #include "readme_iconv.c" keyNew ("system/elektra/modules/iconv/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END); ksAppend (returned, pluginConfig); ksDel (pluginConfig); return 1; } if (!kdbbNeedsUTF8Conversion (handle)) return 0; while ((cur = ksNext (returned)) != 0) { if (keyIsString (cur)) { /* String or similar type of value */ size_t convertedDataSize = keyGetValueSize (cur); char * convertedData = elektraMalloc (convertedDataSize); memcpy (convertedData, keyString (cur), keyGetValueSize (cur)); if (kdbbUTF8Engine (handle, UTF8_FROM, &convertedData, &convertedDataSize)) { ELEKTRA_SET_ERRORF (46, parentKey, "Could not convert string %s, got result %s, encoding settings are from %s to %s", keyString (cur), convertedData, getFrom (handle), getTo (handle)); elektraFree (convertedData); return -1; } keySetString (cur, convertedData); elektraFree (convertedData); } const Key * meta = keyGetMeta (cur, "comment"); if (meta) { /* String or similar type of value */ size_t convertedDataSize = keyGetValueSize (meta); char * convertedData = elektraMalloc (convertedDataSize); memcpy (convertedData, keyString (meta), keyGetValueSize (meta)); if (kdbbUTF8Engine (handle, UTF8_FROM, &convertedData, &convertedDataSize)) { ELEKTRA_SET_ERRORF (46, parentKey, "Could not convert string %s, got result %s, encoding settings are from %s to %s", keyString (meta), convertedData, getFrom (handle), getTo (handle)); elektraFree (convertedData); return -1; } keySetMeta (cur, "comment", convertedData); elektraFree (convertedData); } } return 1; /* success */ }
static int elektraGetDoUpdateWithGlobalHooks (KDB * handle, Split * split, KeySet * ks, Key * parentKey, Key * initialParent, UpdatePass run) { const int bypassedSplits = 1; int pgs_done = 0; int pgc_done = 0; elektraGlobalGet (handle, ks, parentKey, GETSTORAGE, INIT); elektraGlobalGet (handle, ks, parentKey, GETSTORAGE, MAXONCE); // elektraGlobalGet (handle, ks, parentKey, POSTGETSTORAGE, INIT); for (size_t i = 0; i < split->size - bypassedSplits; i++) { if (!test_bit (split->syncbits[i], SPLIT_FLAG_SYNC)) { // skip it, update is not needed continue; } Backend * backend = split->handles[i]; ksRewind (split->keysets[i]); keySetName (parentKey, keyName (split->parents[i])); keySetString (parentKey, keyString (split->parents[i])); int start, end; if (run == FIRST) { start = 1; end = STORAGE_PLUGIN + 1; } else { start = STORAGE_PLUGIN + 1; end = NR_OF_PLUGINS; } for (int p = start; p < end; ++p) { int ret = 0; if (!pgs_done && (p == (STORAGE_PLUGIN + 1)) && handle->globalPlugins[POSTGETSTORAGE][FOREACH]) { pgs_done = 1; keySetName (parentKey, keyName (initialParent)); ksRewind (ks); handle->globalPlugins[POSTGETSTORAGE][FOREACH]->kdbGet (handle->globalPlugins[POSTGETSTORAGE][FOREACH], ks, parentKey); keySetName (parentKey, keyName (split->parents[i])); } else if (!pgc_done && (p == (NR_OF_PLUGINS - 1)) && handle->globalPlugins[POSTGETCLEANUP][FOREACH]) { pgc_done = 1; keySetName (parentKey, keyName (initialParent)); ksRewind (ks); handle->globalPlugins[POSTGETCLEANUP][FOREACH]->kdbGet (handle->globalPlugins[POSTGETCLEANUP][FOREACH], ks, parentKey); keySetName (parentKey, keyName (split->parents[i])); } if (backend->getplugins[p] && backend->getplugins[p]->kdbGet) { if (p <= STORAGE_PLUGIN) { ret = backend->getplugins[p]->kdbGet (backend->getplugins[p], split->keysets[i], parentKey); } else { KeySet * cutKS = prepareGlobalKS (ks, parentKey); ret = backend->getplugins[p]->kdbGet (backend->getplugins[p], cutKS, parentKey); ksAppend (ks, cutKS); ksDel (cutKS); } } if (ret == -1) { // Ohh, an error occurred, // lets stop the process. elektraGlobalError (handle, ks, parentKey, GETSTORAGE, DEINIT); // elektraGlobalError (handle, ks, parentKey, POSTGETSTORAGE, DEINIT); return -1; } } } elektraGlobalGet (handle, ks, parentKey, GETSTORAGE, DEINIT); // elektraGlobalGet (handle, ks, parentKey, POSTGETSTORAGE, DEINIT); return 0; }
/** * Load a plugin. * * The array of plugins must be set to 0. * Its length is NR_OF_PLUGINS. * * systemConfig will only be used, not deleted. * * @param config the config with the information how the * plugins should be put together * @param systemConfig the shared (system) config for the plugins. * Every plugin additional get this config. * * @retval -1 on failure */ int elektraProcessPlugins (Plugin ** plugins, KeySet * modules, KeySet * referencePlugins, KeySet * config, KeySet * systemConfig, Key * errorKey) { Key * root; Key * cur; ksRewind (config); root = ksNext (config); while ((cur = ksNext (config)) != 0) { if (keyRel (root, cur) == 1) { char * pluginName = 0; char * referenceName = 0; int pluginNumber = 0; Key * key; if (elektraProcessPlugin (cur, &pluginNumber, &pluginName, &referenceName, errorKey) == -1) { elektraFree (pluginName); elektraFree (referenceName); ksDel (config); return -1; } if (pluginName) { key = keyDup (cur); keyAddBaseName (key, "config"); KeySet * cutConfig = ksCut (config, key); keyDel (key); KeySet * pluginConfig = elektraRenameKeys (cutConfig, "user"); ksDel (cutConfig); if (!pluginConfig) return -1; ksAppend (pluginConfig, systemConfig); ksRewind (pluginConfig); /* TODO: bug ksAppend invalidates cursor */ /* case 1, we create a new plugin, note that errorKey is not passed here, because it would set error information but we only want a warning instead. */ plugins[pluginNumber] = elektraPluginOpen (pluginName, modules, pluginConfig, errorKey); if (!plugins[pluginNumber]) { ELEKTRA_ADD_WARNING (64, errorKey, pluginName); /* Loading plugin did not work */ elektraFree (pluginName); elektraFree (referenceName); ksDel (config); return -1; } /* case 2, we label it for later use */ if (referenceName) ksAppendKey (referencePlugins, keyNew (referenceName, KEY_BINARY, KEY_SIZE, sizeof (plugins[pluginNumber]), KEY_VALUE, &plugins[pluginNumber], KEY_END)); } else { /* case 3, we use an existing plugin */ Key * lookup = ksLookup (referencePlugins, keyNew (referenceName, KEY_END), KDB_O_DEL); if (!lookup) { ELEKTRA_ADD_WARNING (65, errorKey, referenceName); /* Getting a reference plugin at a previous stage did not work. Note that this check is necessary, because loading the plugin could fail for example at errorplugins and at a later point, for example at setplugins it is tried to refer to that.*/ elektraFree (referenceName); ksDel (config); return -1; } plugins[pluginNumber] = *(Plugin **)keyValue (lookup); ++plugins[pluginNumber]->refcounter; } elektraFree (pluginName); elektraFree (referenceName); } else { ELEKTRA_ADD_WARNING (21, errorKey, keyString (cur)); } } ksDel (config); return 0; }
int elektraCsvstorageGet(Plugin *handle, KeySet *returned, Key *parentKey) { if (!strcmp(keyName(parentKey), "system/elektra/modules/csvstorage")) { KeySet *contract = ksNew (30, keyNew ("system/elektra/modules/csvstorage", KEY_VALUE, "csvstorage plugin waits for your orders", KEY_END), keyNew ("system/elektra/modules/csvstorage/exports", KEY_END), keyNew ("system/elektra/modules/csvstorage/exports/get", KEY_FUNC, elektraCsvstorageGet, KEY_END), keyNew ("system/elektra/modules/csvstorage/exports/set", KEY_FUNC, elektraCsvstorageSet, KEY_END), #include ELEKTRA_README(csvstorage) keyNew ("system/elektra/modules/csvstorage/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), KS_END); ksAppend (returned, contract); ksDel (contract); return 1; /* success */ } KeySet *config = elektraPluginGetConfig(handle); Key *delimKey = ksLookupByName(config, "/delimiter", 0); char delim = ';'; if(delimKey) { const char *delimString = keyString(delimKey); delim = delimString[0]; } Key *readHeaderKey = ksLookupByName(config, "/header", 0); short useHeader = 0; if(readHeaderKey) { const char *printHeaderString = keyString(readHeaderKey); if(!strcmp(printHeaderString, "colname")) { useHeader = 1; } else if(!(strcmp(printHeaderString, "skip"))) { useHeader = -1; } else if(!(strcmp(printHeaderString, "record"))) { useHeader = 0; } else { useHeader = 0; } } unsigned long fixColumnCount = 0; Key *fixColumnCountKey = ksLookupByName(config, "/columns", 0); if(fixColumnCountKey) { if(keyString(fixColumnCountKey)) { fixColumnCount = atol(keyString(fixColumnCountKey)); } } Key *setNamesKey = ksLookupByName(config, "/columns/names", 0); char *colNames = NULL; if(setNamesKey) { if(fixColumnCountKey) { KeySet *namesKS = ksCut(config, setNamesKey); unsigned long nrNames = (unsigned long)ksGetSize(namesKS)-1; if(nrNames == fixColumnCount) { colNames = (char *)elektraMalloc(nrNames*sizeof(char *)); Key *cur; char **ptr = (char **)colNames; while((cur = ksNext(namesKS)) != NULL) { if(!strcmp(keyName(cur), keyName(setNamesKey))) continue; if(!strcmp(keyString(cur), "")) *ptr = NULL; else *ptr = (char *)keyString(cur); ++ptr; } } ksAppend(config, namesKS); ksDel(namesKS); } } int nr_keys; nr_keys = csvRead(returned, parentKey, delim, useHeader, fixColumnCount, (const char **)colNames); if(colNames) elektraFree(colNames); if (nr_keys == -1) return -1; return 1; }
int elektraSimpleiniGet (Plugin * handle, KeySet * returned, Key * parentKey) { /* get all keys */ if (!strcmp (keyName (parentKey), "system/elektra/modules/simpleini")) { KeySet * moduleConfig = ksNew ( 30, keyNew ("system/elektra/modules/simpleini", KEY_VALUE, "simpleini plugin waits for your orders", KEY_END), keyNew ("system/elektra/modules/simpleini/exports", KEY_END), keyNew ("system/elektra/modules/simpleini/exports/get", KEY_FUNC, elektraSimpleiniGet, KEY_END), keyNew ("system/elektra/modules/simpleini/exports/set", KEY_FUNC, elektraSimpleiniSet, KEY_END), #include "readme_simpleini.c" keyNew ("system/elektra/modules/simpleini/infos/version", KEY_VALUE, PLUGINVERSION, KEY_END), keyNew ("system/elektra/modules/simpleini/config/needs", KEY_VALUE, "the needed configuration to work in a backend", KEY_END), keyNew ("system/elektra/modules/simpleini/config/needs/chars", KEY_VALUE, "Characters needed", KEY_END), // space in value now works: // TODO: characters present in format should be escaped /* keyNew ("system/elektra/modules/simpleini/config/needs/chars/20", KEY_VALUE, "61", KEY_END), // space -> a keyNew ("system/elektra/modules/simpleini/config/needs/chars/23", KEY_VALUE, "62", KEY_END), // # -> b keyNew ("system/elektra/modules/simpleini/config/needs/chars/25", KEY_VALUE, "63", KEY_END), // % -> c (escape character) keyNew ("system/elektra/modules/simpleini/config/needs/chars/3B", KEY_VALUE, "64", KEY_END), // ; -> d keyNew ("system/elektra/modules/simpleini/config/needs/chars/3D", KEY_VALUE, "65", KEY_END), // = -> e keyNew ("system/elektra/modules/simpleini/config/needs/chars/5C", KEY_VALUE, "66", KEY_END), // \\ -> f */ keyNew ("system/elektra/modules/simpleini/config/needs/chars/0A", KEY_VALUE, "67", KEY_END), // enter (NL) -> g keyNew ("system/elektra/modules/simpleini/config/needs/chars/0D", KEY_VALUE, "68", KEY_END), // CR -> h keyNew ("system/elektra/modules/simpleini/config/needs/escape", KEY_VALUE, "25", KEY_END), KS_END); ksAppend (returned, moduleConfig); ksDel (moduleConfig); return 1; } char * key = 0; char * value = 0; int errnosave = errno; FILE * fp = fopen (keyString (parentKey), "r"); if (!fp) { ELEKTRA_SET_ERROR_GET (parentKey); errno = errnosave; return -1; } char * format = getFormat (handle, "%ms", "%m[^\n]"); ELEKTRA_LOG ("Read from '%s' with format '%s'", keyString (parentKey), format); int n = 0; size_t size = 0; ssize_t ksize = 0; #pragma GCC diagnostic ignored "-Wformat" // icc warning #269: invalid format string conversion while ((n = fscanf (fp, format, &key, &value)) >= 0) { ELEKTRA_LOG_DEBUG ("Read %d parts: '%s' with value '%s'", n, key, value); if (n == 0) { // discard line getline (&key, &size, fp); ELEKTRA_LOG_DEBUG ("Discard '%s'", key); elektraFree (key); key = 0; continue; } Key * read = keyNew (keyName (parentKey), KEY_END); if (keyAddName (read, key) == -1) { ELEKTRA_ADD_WARNING (ELEKTRA_WARNING_INVALID_KEY, parentKey, key); keyDel (read); continue; } if (n == 2) { keySetString (read, value); elektraFree (value); value = 0; } if (ksAppendKey (returned, read) != ksize + 1) { ELEKTRA_SET_ERROR (ELEKTRA_ERROR_NOEOF, parentKey, "duplicated key"); return -1; } ++ksize; elektraFree (key); key = 0; } if (feof (fp) == 0) { elektraFree (format); fclose (fp); ELEKTRA_SET_ERROR (ELEKTRA_ERROR_NOEOF, parentKey, "not at the end of file"); return -1; } elektraFree (format); fclose (fp); return 1; /* success */ }