/**@return a backend which gives plugin configuration of the module * which is currently point to. * * @param modules the modules to work with * @param errorKey the key to issue warnings and errors to */ Backend* elektraBackendOpenModules(KeySet *modules, Key *errorKey) { Backend *backend = elektraBackendAllocate(); cursor_t save = ksGetCursor (modules); KeySet *defaultConfig = ksNew(5, keyNew("system/module", KEY_VALUE, "1", KEY_END), keyNew("user/module", KEY_VALUE, "1", KEY_END), KS_END); Key *cur = ksCurrent(modules); Plugin *plugin = elektraPluginOpen(keyBaseName(cur), modules, defaultConfig, errorKey); if (!plugin) { /* Error already set in plugin */ elektraFree(backend); return 0; } Key *mp = keyNew ("system/elektra/modules", KEY_VALUE, "modules", KEY_END); keyAddBaseName (mp, keyBaseName(cur)); backend->getplugins[0] = plugin; plugin->refcounter = 1; backend->mountpoint = mp; keyIncRef(backend->mountpoint); ksSetCursor (modules, save); return backend; }
static void elektraDropCurrentKey (KeySet * ks, Key * warningKey, const Backend * curHandle, const char * msg) { const Key * k = ksCurrent (ks); const size_t sizeOfStaticText = 100; char * warningMsg = elektraMalloc (keyGetNameSize (curHandle->mountpoint) + keyGetValueSize (curHandle->mountpoint) + keyGetNameSize (k) + strlen (msg) + sizeOfStaticText); strcpy (warningMsg, "drop key "); const char * name = keyName (k); if (name) { strcat (warningMsg, name); } else { strcat (warningMsg, "(no name)"); } strcat (warningMsg, " not belonging to "); strcat (warningMsg, keyName (curHandle->mountpoint)); strcat (warningMsg, " with name "); strcat (warningMsg, keyString (curHandle->mountpoint)); strcat (warningMsg, " because "); strcat (warningMsg, msg); ELEKTRA_ADD_WARNING (79, warningKey, warningMsg); elektraFree (warningMsg); cursor_t c = ksGetCursor (ks); keyDel (elektraKsPopAtCursor (ks, c)); ksSetCursor (ks, c); elektraKsPrev (ks); // next ksNext() will point correctly again }
/** * @brief return only those keys from the given * keyset that pass the supplied filter function * with the supplied argument * * @param result the keyset that should contain the filtered keys * @param input the keyset whose keys should be filtered * @param filter a function pointer to a function that will be used to * filter the keyset. A key will be taken if the function returns a value * greater than 0. * @param argument an argument that will be passed to the filter function * each time it is called * @return the number of filtered keys if the filter function always * returned a positive value, -1 otherwise * @retval NULL on NULL pointer */ int elektraKsFilter (KeySet *result, KeySet *input, int (*filter) (const Key *k, void *argument), void *argument) { if (!result) return -1; if (!input) return -1; if (!filter) return -1; int rc = 0; int ret = 0; Key *current; cursor_t cursor = ksGetCursor (input); ksRewind (input); while ((current = ksNext (input)) != 0) { rc = filter (current, argument); if (rc <= -1) return -1; else if (rc > 0) { ++ ret; ksAppendKey(result, keyDup (current)); } } ksSetCursor(input, cursor); return ret; }
/* The KeySet MUST be sorted alphabetically (or at least ascending * by the length of keynames) for this function to work */ static Key * findNearestParent (Key * key, KeySet * ks) { Key * current; ksSetCursor (ks, ksGetSize (ks) - 1); while ((current = ksPrev (ks)) != 0) { if (keyIsBelow (current, key)) { return current; } } return 0; }
/**A functional access to keys. * * Instead of writing your own loop you can write * a function working with a key and pass it to * this method. * * The function will be executed for all keys in * the keyset. * * @param ks the keyset to work with * @param func the function to execute on every key of the keyset * @return the sum of all return values * @retval -1 if any function returned -1, the execution will stop there, but * ksCurrent() will tell you where it stopped. * @see ksFilter() */ int ksForEach (KeySet * ks, int (*func) (Key * k)) { int ret = 0; Key * current; cursor_t cursor = ksGetCursor (ks); ksRewind (ks); while ((current = ksNext (ks)) != 0) { int rc = func (current); if (rc == -1) return -1; ret += rc; } ksSetCursor (ks, cursor); return ret; }
static int handleErrors (Key * parentKey, KeySet * ks, Key * key, Key * specKey, ConflictHandling * ch, Direction dir) { cursor_t cursor = ksGetCursor (ks); int ret = 0; ConflictHandling * localCh = elektraMalloc (sizeof (ConflictHandling)); memcpy (localCh, ch, sizeof (ConflictHandling)); parseLocalConfig (specKey, localCh, dir); Key * parentLookup = keyDup (key); keySetBaseName (parentLookup, 0); Key * parent = ksLookup (ks, parentLookup, KDB_O_NONE); keyDel (parentLookup); keyRewindMeta (parent); Conflict conflict; Key * meta; while (keyNextMeta (parent) != NULL) { meta = (Key *) keyCurrentMeta (parent); conflict = getConflict (meta); if (conflict != NAC) { ret |= handleError (parentKey, parent, specKey, meta, conflict, localCh); keySetMeta (parent, keyName (meta), 0); } else if (!strncmp (keyName (meta), "conflict/#", 10) || !strncmp (keyName (meta), "conflict/invalid/hasmember/#", 28)) { keySetMeta (parent, keyName (meta), 0); } } keyRewindMeta (key); while (keyNextMeta (key) != NULL) { meta = (Key *) keyCurrentMeta (key); conflict = getConflict (meta); if (conflict != NAC) { ret |= handleError (parentKey, key, specKey, meta, conflict, localCh); keySetMeta (key, keyName (meta), 0); } else if (!strncmp (keyName (meta), "conflict/#", 10) || !strncmp (keyName (meta), "conflict/invalid/hasmember/#", 28)) { keySetMeta (key, keyName (meta), 0); } } elektraFree (localCh); ksSetCursor (ks, cursor); return ret; }
static int elektraKeySetMetaKeySet (Key * key, KeySet * metaKeySet) { if (!key) return 0; if (!metaKeySet) return 0; Key * currentMeta; cursor_t initialCursor = ksGetCursor (metaKeySet); ksRewind (metaKeySet); while ((currentMeta = ksNext (metaKeySet))) { keySetMeta (key, keyName (currentMeta), keyString (currentMeta)); } ksSetCursor (metaKeySet, initialCursor); return 1; }
/**Filter a keyset. * * filter is executed for every key in the keyset result. When it returns 0, * the key will be dropped, when it returns 1 it will be ksAppendKey()ed to result, * when it returns -1 the processing will be stopped. You can use ksCurrent() * on input to see where the problem was. Because of this input is not const, * apart from ksCurrent() the input will not be changed. The keys that have * been in result before will stay untouched. * * @param result is the keyset where keys are added. * @param input is the keyset the filter works on. * @param filter is the function to execute on every key of the keyset to decide if * it should be ksAppendKey()ed to the result. * @return the number of keys added on success * @retval 0 when nothing was done * @retval -1 when filter returned an error (-1), ksCurrent() of input will * be the problematic key. * @see ksForEach() **/ int ksFilter (KeySet *result, KeySet *input, int (*filter) (Key *k)) { int rc = 0; int ret = 0; Key *current; cursor_t cursor = ksGetCursor (input); ksRewind (input); while ((current = ksNext (input)) != 0) { rc = filter (current); if (rc == -1) return -1; else if (rc != 0) { ++ ret; ksAppendKey(result, keyDup (current)); } } ksSetCursor(input, cursor); return ret; }
/** * Builds an array of pointers to the keys in the supplied keyset. * The keys are not copied, calling keyDel may remove them from * the keyset. * * The size of the buffer can be easily allocated via ksGetSize. Example: * @code * KeySet *ks = somekeyset; * Key **keyArray = calloc (ksGetSize(ks), sizeof (Key *)); * elektraKsToMemArray (ks, keyArray); * ... work with the array ... * elektraFree (keyArray); * @endcode * * @param ks the keyset object to work with * @param buffer the buffer to put the result into * @return the number of elements in the array if successful * @return a negative number on null pointers or if an error occurred */ int elektraKsToMemArray (KeySet * ks, Key ** buffer) { if (!ks) return -1; if (!buffer) return -1; /* clear the received buffer */ memset (buffer, 0, ksGetSize (ks) * sizeof (Key *)); cursor_t cursor = ksGetCursor (ks); ksRewind (ks); size_t idx = 0; Key * key; while ((key = ksNext (ks)) != 0) { buffer[idx] = key; ++idx; } ksSetCursor (ks, cursor); return idx; }
/** * @internal * * Calculates the common parent to all keys in @p ks. * * This is a c-helper function, you need not implement it in bindings. * * Given the @p ks KeySet, calculates the parent name for all the keys. * So if @p ks contains this keys: * * @code * system/sw/xorg/Monitors/Monitor1/vrefresh * system/sw/xorg/Monitors/Monitor1/hrefresh * system/sw/xorg/Devices/Device1/driver * system/sw/xorg/Devices/Device1/mode * @endcode * * The common parent is @p system/sw/xorg . * * On the other hand, if we have this KeySet: * * @code * system/some/thing * system/other/thing * user/unique/thing * @endcode * * No common parent is possible, so @p returnedCommonParent will contain nothing. * * @param working the Keyset to work with * @param returnedCommonParent a pre-allocated buffer that will receive the * common parent, if found * @param maxSize size of the pre-allocated @p returnedCommonParent buffer * @return size in bytes of the parent name, or 0 if there is no common parent, * or -1 to indicate an error, then @p errno must be checked. */ ssize_t ksGetCommonParentName (const KeySet * working, char * returnedCommonParent, size_t maxSize) { size_t parentSize = 0; Key * current = 0; cursor_t cinit; KeySet * ks; ssize_t sMaxSize; if (maxSize > SSIZE_MAX) return -1; sMaxSize = maxSize; cinit = ksGetCursor (working); ks = (KeySet *)working; if (ksGetSize (ks) < 1) return 0; ksRewind (ks); current = ksNext (ks); if (keyGetNameSize (current) > sMaxSize) { /*errno=KDB_ERR_TRUNC;*/ returnedCommonParent[0] = 0; return -1; } strcpy (returnedCommonParent, keyName (current)); parentSize = elektraStrLen (returnedCommonParent); while (*returnedCommonParent) { ksRewind (ks); while ((current = ksNext (ks)) != 0) { /* Test if a key doesn't match */ if (memcmp (returnedCommonParent, keyName (current), parentSize - 1)) break; } if (current) { /* some key failed to be a child */ /* parent will be the parent of current parent... */ char * delim = 0; // TODO: does not honor escaped characters if ((delim = strrchr (returnedCommonParent, KDB_PATH_SEPARATOR))) { *delim = 0; parentSize = elektraStrLen (returnedCommonParent); } else { *returnedCommonParent = 0; parentSize = 0; break; /* Better don't make comparison with parentSize-1 now */ } } else { /* All keys matched (current==0) */ /* We have our common parent to return in commonParent */ ksSetCursor (ks, cinit); return parentSize; } } ksSetCursor (ks, cinit); return parentSize; /* if reached, will be zero */ }