static void test_ksToArray ()
{
	KeySet * ks = ksNew (5, keyNew ("user/test1", KEY_END), keyNew ("user/test2", KEY_END), keyNew ("user/test3", KEY_END), KS_END);

	Key ** keyArray = calloc (ksGetSize (ks), sizeof (Key *));
	elektraKsToMemArray (ks, keyArray);

	succeed_if_same_string ("user/test1", keyName (keyArray[0]));
	succeed_if_same_string ("user/test2", keyName (keyArray[1]));
	succeed_if_same_string ("user/test3", keyName (keyArray[2]));

	/* test if cursor is restored */
	ksNext (ks);
	cursor_t cursor = ksGetCursor (ks);
	elektraKsToMemArray (ks, keyArray);

	succeed_if (ksGetCursor (ks) == cursor, "cursor was not restored");

	succeed_if (elektraKsToMemArray (0, keyArray) < 0, "wrong result on null pointer");
	succeed_if (elektraKsToMemArray (ks, 0) < 0, "wrong result on null buffer");
	KeySet * empty = ksNew (0, KS_END);
	succeed_if (elektraKsToMemArray (empty, keyArray) == 0, "wrong result on empty keyset");
	ksDel (empty);

	elektraFree (keyArray);
	ksDel (ks);
}
Beispiel #2
0
void test_hostLensDelete(char *sourceFile, char *compFile)
{
	Key *parentKey = keyNew ("user/tests/augeas-hosts", KEY_VALUE,
			srcdir_file (sourceFile), KEY_END);
	KeySet *conf = ksNew (20,
			keyNew ("system/lens", KEY_VALUE, "Hosts.lns", KEY_END), KS_END);
	PLUGIN_OPEN("augeas");

	KeySet *ks = ksNew(0, KS_END);

	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/tests/augeas-hosts/1", 0);
	exit_if_fail(key, "localhost not found");
	ksPopAtCursor(ks, ksGetCursor(ks));
	keyDel (key);

	key = ksLookupByName (ks, "user/tests/augeas-hosts/1/ipaddr", 0);
	exit_if_fail(key, "ip address of localhost not found");
	ksPopAtCursor(ks, ksGetCursor(ks));
	keyDel (key);

	key = ksLookupByName (ks, "user/tests/augeas-hosts/1/canonical", 0);
	exit_if_fail(key, "canonical of localhost not found");
	ksPopAtCursor(ks, ksGetCursor(ks));
	keyDel (key);

	key = ksLookupByName (ks, "user/tests/augeas-hosts/1/#comment", 0);
	exit_if_fail(key, "comment of localhost not found");
	ksPopAtCursor(ks, ksGetCursor(ks));
	keyDel (key);

	keySetString (parentKey, elektraFilename());

	succeed_if(plugin->kdbSet (plugin, ks, parentKey) == 1,
			"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 (compFile), keyString (parentKey)),
			"files do not match as expected");

	ksDel (ks);

	elektraUnlink(keyString (parentKey));
	keyDel (parentKey);

	PLUGIN_CLOSE ()
	;

}
Beispiel #3
0
/**@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;
}
Beispiel #4
0
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
}
Beispiel #5
0
/**
 * @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;
}
Beispiel #6
0
static void test_ksPopAtCursor()
{
	KeySet *ks = ksNew (
		5,
		keyNew ("user/valid/key1", KEY_END),
		keyNew ("user/valid/key2", KEY_END),
		keyNew ("system/valid/key1", KEY_END),
		keyNew ("system/valid/key2", KEY_END),
		KS_END);
	KeySet *ks_c = ksNew (
		5,
		keyNew ("user/valid/key1", KEY_END),
		keyNew ("user/valid/key2", KEY_END),
		keyNew ("system/valid/key1", KEY_END),
		KS_END);
	ksRewind(ks);
	ksNext(ks);
	ksNext(ks);
	cursor_t c = ksGetCursor(ks);
	keyDel (ksPopAtCursor(ks, c));
	succeed_if(ksCurrent(ks) == 0, "cursor position wrong");

	compare_keyset(ks, ks_c);
	ksDel(ks);
	ksDel(ks_c);
}
Beispiel #7
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;
}
Beispiel #8
0
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;
}
Beispiel #9
0
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;
}
Beispiel #11
0
/**
 * 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;
}
Beispiel #12
0
/**
 * @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 */
}