예제 #1
0
static void testwritevalidemptycol (const char * file)
{

	Key * parentKey = keyNew ("user/tests/csvstorage", KEY_VALUE, srcdir_file (file), KEY_END);
	KeySet * conf = ksNew (20, keyNew ("system/delimiter", KEY_VALUE, ";", KEY_END),
			       keyNew ("system/header", KEY_VALUE, "colname", KEY_END), KS_END);

	KeySet * ks = ksNew (0, KS_END);
	PLUGIN_OPEN ("csvstorage");
	succeed_if (plugin->kdbGet (plugin, ks, parentKey) > 0, "call to kdbGet was not successful");
	keySetString (parentKey, elektraFilename ());
	succeed_if (plugin->kdbSet (plugin, ks, parentKey) >= 0, "error: couldn't write data");
	ksDel (ks);
	keyDel (parentKey);
	PLUGIN_CLOSE ();
}
예제 #2
0
static void test_lookupNoascading ()
{
	printf ("Test lookup without cascading\n");

	Key * specKey = keyNew ("/abc", KEY_CASCADING_NAME, KEY_END);

	Key * d = keyDup (specKey);
	keySetString (d, "dup");
	succeed_if_same_string (keyName (specKey), "/abc");
	succeed_if_same_string (keyName (d), "/abc");

	succeed_if (!keyCmp (d, specKey), "comparision to duplicate failed");
	succeed_if_same_string (keyName (d), "/abc");
	succeed_if_same_string (keyName (specKey), "/abc");

	KeySet * ks = ksNew (20, d, KS_END);

	Key * k = ksLookup (ks, specKey, KDB_O_NOCASCADING);
	succeed_if_same_string (keyName (specKey), "/abc");
	succeed_if (k != 0, "did not find cascading key");
	succeed_if (k != specKey, "should not be specKey");
	succeed_if (k == d, "should be dup key");

	Key * a = keyNew (keyName (specKey), KEY_CASCADING_NAME, KEY_VALUE, "a", KEY_END);
	ksAppendKey (ks, a);

	for (int i = 0; i < 5; ++i)
	{
		k = ksLookup (ks, specKey, KDB_O_NOCASCADING);
		succeed_if (keyGetNameSize (specKey) == 5, "size of spec key wrong");
		succeed_if_same_string (keyName (specKey), "/abc");
		succeed_if (k != 0, "did not find cascading key");
		succeed_if (k != specKey, "should not be specKey");
		succeed_if (k == a, "should be dup key");

		// search without cascading
		k = ksLookup (ks, specKey, 0);
		succeed_if (keyGetNameSize (specKey) == 5, "size of spec key wrong");
		succeed_if_same_string (keyName (specKey), "/abc");
		succeed_if (k != 0, "did not find cascading key");
		succeed_if (k != specKey, "should not be specKey");
		succeed_if (k == a, "should be dup key");
	}

	ksDel (ks);
	keyDel (specKey);
}
예제 #3
0
파일: ini.c 프로젝트: tryge/libelektra
// TODO: this is very similar to elektraKeyAppendMetaLine in keytometa
static int elektraKeyAppendLine (Key *target, const char *line)
{
	if (!target) return 0;
	if (!line) return 0;


	char *buffer = elektraMalloc (keyGetValueSize(target) + strlen (line) + 1);
	if (!buffer) return 0;

	keyGetString(target, buffer, keyGetValueSize(target));
	strcat (buffer, "\n");
	strncat (buffer, line, strlen (line));

	keySetString(target, buffer);
	elektraFree (buffer);
	return keyGetValueSize(target);
}
예제 #4
0
static int elektraResolveFilename (Key * parentKey, ElektraResolveTempfile tmpFile)
{
	int rc = 0;
	void * handle = elektraInvokeOpen ("resolver", 0, 0);
	if (!handle)
	{
		rc = -1;
		goto RESOLVE_FAILED;
	}
	ElektraResolved * resolved = NULL;
	typedef ElektraResolved * (*resolveFileFunc) (elektraNamespace, const char *, ElektraResolveTempfile, Key *);
	resolveFileFunc resolveFunc = *(resolveFileFunc *) elektraInvokeGetFunction (handle, "filename");

	if (!resolveFunc)
	{
		rc = -1;
		goto RESOLVE_FAILED;
	}

	typedef void (*freeHandleFunc) (ElektraResolved *);
	freeHandleFunc freeHandle = *(freeHandleFunc *) elektraInvokeGetFunction (handle, "freeHandle");

	if (!freeHandle)
	{
		rc = -1;
		goto RESOLVE_FAILED;
	}

	resolved = resolveFunc (keyGetNamespace (parentKey), keyString (parentKey), tmpFile, parentKey);

	if (!resolved)
	{
		rc = -1;
		goto RESOLVE_FAILED;
	}
	else
	{
		keySetString (parentKey, resolved->fullPath);
		freeHandle (resolved);
	}

RESOLVE_FAILED:
	elektraInvokeClose (handle, 0);
	return rc;
}
예제 #5
0
static void test_keySetString (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 = metaTestKeySet ();
	const char * name = "user/tests/storage/specialkey";
	const char * value = "special value";
	size_t realValueSize = elektraStrLen (value);
	Key * key = keyNew (name, KEY_VALUE, value, KEY_END);
	ksAppendKey (ks, key);
	succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "kdbSet was not successful");
	succeed_if (plugin->kdbGet (plugin, ks, parentKey) == 1, "kdbGet was not successful");

	Key * found = ksLookupByName (ks, name, KDB_O_POP);
	succeed_if (found, "did not find key");

	// now set a new key string to the Key _after_ kdbGet
	const char * newValue = "some new special value";
	size_t newValueSize = elektraStrLen (newValue);

	succeed_if (keySetString (found, newValue) == (ssize_t) newValueSize, "Key string could not be set");

	ksAppendKey (ks, found);
	succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "kdbSet was not successful");
	succeed_if (plugin->kdbGet (plugin, ks, parentKey) == 1, "kdbGet was not successful");

	found = ksLookupByName (ks, name, 0);
	succeed_if (found, "did not find key");

	ssize_t apiValueSize = keyGetValueSize (found);
	char * apiValue = elektraMalloc (apiValueSize);
	succeed_if (keyGetString (found, apiValue, apiValueSize) == (ssize_t) newValueSize, "Key string has wrong size");

	succeed_if (elektraStrNCmp (value, apiValue, realValueSize) != 0, "Key string value is wrong");
	succeed_if (elektraStrNCmp (newValue, apiValue, newValueSize) == 0, "Key string value is wrong");

	elektraFree (apiValue);
	keyDel (parentKey);
	ksDel (ks);
	closeStoragePlugin (storagePlugin);
}
예제 #6
0
파일: augeas.c 프로젝트: beku/libelektra
static int convertToKey(augeas *handle, const char *treePath, void *data)
{
	struct KeyConversion *conversionData = (struct KeyConversion *) data;
	int result = 0;
	const char *value = 0;
	result = aug_get (handle, treePath, &value);

	if (result < 0) return result;

	Key *key = createKeyFromPath (conversionData->parentKey, treePath);

	/* fill key values */
	keySetString (key, value);
	conversionData->currentOrder++;
	keySetOrderMeta (key, conversionData->currentOrder);
	result = ksAppendKey (conversionData->ks, key);

	return result;
}
예제 #7
0
파일: ini.c 프로젝트: intfrr/libelektra
static int iniKeyToElektraKey (void *vconfig, const char *section, const char *name, const char *value)
{

	Configuration *config = (Configuration *)vconfig;

	Key *appendKey = keyDup (config->parentKey);

	if (section)
	{
		keyAddBaseName(appendKey, section);
	}

	keyAddBaseName (appendKey, name);
	writeCommentToMeta (config, appendKey);
	keySetString (appendKey, value);
	ksAppendKey (config->result, appendKey);

	return 1;
}
예제 #8
0
static void test_file_crypto_operations (void)
{
	Plugin * plugin = NULL;
	Key * parentKey = keyNew ("system", KEY_END);
	KeySet * modules = ksNew (0, KS_END);
	KeySet * config = newPluginConfiguration ();

	elektraModulesInit (modules, 0);
	plugin = elektraPluginOpen (PLUGIN_NAME, modules, config, 0);
	succeed_if (plugin, "failed to open plugin handle");
	if (plugin)
	{
		KeySet * data = ksNew (0, KS_END);
		const char * tmpFile = elektraFilename ();
		if (tmpFile)
		{
			// prepare test file to be encrypted
			writeTestFile (tmpFile);
			keySetString (parentKey, tmpFile);

			// try to encrypt the file
			succeed_if (plugin->kdbSet (plugin, data, parentKey) == 1, "kdb set failed");
			succeed_if (isTestFileCorrect (tmpFile) == -1, "file content did not change during encryption");

			// try to decrypt the file again (simulating the pregetstorage call)
			succeed_if (plugin->kdbGet (plugin, data, parentKey) == 1, "kdb get (pregetstorage) failed");
			succeed_if (isTestFileCorrect (keyString (parentKey)) == 1, "file content could not be restored during decryption");

			// a second call to kdb get (the postgetstorage call) should re-encrypt the file again
			succeed_if (plugin->kdbGet (plugin, data, parentKey) == 1, "kdb get (postgetstorage) failed");
			succeed_if (isTestFileCorrect (tmpFile) == -1, "postgetstorage did not encrypt the file again");

			remove (tmpFile);
		}

		ksDel (data);
		elektraPluginClose (plugin, 0);
	}

	elektraModulesClose (modules, 0);
	ksDel (modules);
	keyDel (parentKey);
}
예제 #9
0
void test_json (const char * fileName, KeySet * compareKeySet, KeySet * conf)
{
	printf ("Test json with %s\n", srcdir_file (fileName));

	Plugin * plugin = elektraPluginOpen ("yajl", modules, conf, 0);
	exit_if_fail (plugin != 0, "could not open plugin");
	// printf ("Test with %s\n", srcdir_file(fileName));

	Key * parentKey = keyNew ("user/tests/yajl", KEY_VALUE, srcdir_file (fileName), KEY_END);
	KeySet * keys = ksNew (0, KS_END);
	succeed_if (plugin->kdbGet (plugin, keys, parentKey) == 1, "kdbGet was not successful");
	succeed_if (output_error (parentKey), "error in kdbGet");
	succeed_if (output_warnings (parentKey), "warnings in kdbGet");

	/*
	output_keyset(keys);
	output_keyset(compareKeySet);
	*/
	compare_keyset (keys, compareKeySet);

	keySetString (parentKey, elektraFilename ());
	// printf("File name is: %s\n", keyString(parentKey));

	succeed_if (plugin->kdbSet (plugin, keys, 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 (fileName), keyString (parentKey)), "files do not match as expected");
	elektraUnlink (keyString (parentKey));

	/*
	printf ("The keys we read out are:\n");
	output_keyset(keys);
	printf ("The keys we compared it with:\n");
	output_keyset(compareKeySet);
	*/

	keyDel (parentKey);
	ksDel (keys);
	ksDel (compareKeySet);

	elektraPluginClose (plugin, 0);
}
예제 #10
0
void test_ro()
{
	Key *key;

	key = keyNew(KEY_END);
	key->flags |= KEY_FLAG_RO;

	succeed_if (keySetString(key, "a") == -1, "read only string, not allowed to set");
	succeed_if (keySetBinary(key, "a", 2) == -1, "read only string, not allowed to set");
	succeed_if (keySetName(key, "user") == -1, "read only string, not allowed to set");
	succeed_if (keySetMeta(key, "meta", "value") == -1, "read only string, not allowed to set");

	keyDel (key);

	key = keyNew(KEY_END);
	succeed_if (keySetMeta(key, "meta", "value") == sizeof("value"), "could not set meta");

	// TODO check if RO
	keyDel (key);
}
예제 #11
0
파일: meta.c 프로젝트: reox/libelektra
void elektraMetaArrayAdd (Key * key, const char * metaName, const char * value)
{
	const Key * meta = keyGetMeta (key, metaName);
	Key * arrayKey;
	if (!meta)
	{
		keySetMeta (key, metaName, "#0");
		arrayKey = keyDup (keyGetMeta (key, metaName));
		keySetString (arrayKey, 0);
		keyAddBaseName (arrayKey, "#");
	}
	else
	{
		arrayKey = keyDup (meta);
		keyAddBaseName (arrayKey, keyString (meta));
	}
	elektraArrayIncName (arrayKey);
	keySetMeta (key, keyName (arrayKey), value);
	keySetMeta (key, metaName, keyBaseName (arrayKey));
	keyDel (arrayKey);
}
예제 #12
0
static int elektraYajlParseString (void * ctx, const unsigned char * stringVal, yajl_size_type stringLen)
{
	KeySet * ks = (KeySet *)ctx;
	elektraYajlIncrementArrayEntry (ks);

	Key * current = ksCurrent (ks);

	unsigned char delim = stringVal[stringLen];
	char * stringValue = (char *)stringVal;
	stringValue[stringLen] = '\0';

#ifdef ELEKTRA_YAJL_VERBOSE
	printf ("elektraYajlParseString %s %d\n", stringVal, stringLen);
#endif

	keySetString (current, stringValue);

	// restore old character in buffer
	stringValue[stringLen] = delim;
	return 1;
}
예제 #13
0
static void test_simpleCutRestoreOnSet () {
	Key *parentKey = keyNew ("user/tests/rename", KEY_END);
	Key *parentKeyCopy = keyDup(parentKey);
	KeySet *conf = ksNew (20,
			keyNew ("system/cut", KEY_VALUE, "will/be/stripped", KEY_END), KS_END);
	PLUGIN_OPEN("rename");

	KeySet *ks = createSimpleTestKeys();
	ksAppendKey(ks, parentKey);

	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");

	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");

	/* test that the keys have been correctly restored */
	KeySet *expected = createSimpleTestKeys();

	/* the parent key is restored from user/tests/rename/will/be/stripped
	 * and therefore will have its key value
	 */
	keySetString (parentKeyCopy, "value3");
	ksAppendKey (expected, parentKeyCopy);

	compareKeySets (ks, expected);
	ksDel(expected);
	ksDel(ks);

	/*
	 * this has to be done because the parentKey is not
	 * part of ks anymore due to renaming
	 */
	keyDel(parentKey);
	PLUGIN_CLOSE ();
}
예제 #14
0
파일: backend.c 프로젝트: beku/libelektra
/**
 * Opens the internal backend that indicates that a backend
 * is missing at that place.
 *
 * @return the fresh allocated backend or 0 if no memory
 */
Backend* elektraBackendOpenMissing(Key *mp)
{
	Backend *backend = elektraBackendAllocate();

	Plugin *plugin = elektraPluginMissing();
	if (!plugin)
	{
		/* Could not allocate plugin */
		elektraFree(backend);
		return 0;
	}

	backend->getplugins[0] = plugin;
	backend->setplugins[0] = plugin;
	plugin->refcounter = 2;

	keySetString (mp, "missing");
	backend->mountpoint = mp;
	keyIncRef(backend->mountpoint);

	return backend;
}
예제 #15
0
void testRoundTrip (const char * fileName)
{
	Key * parentKey = keyNew ("user/tests/file", KEY_VALUE, srcdir_file (fileName), KEY_END);

	KeySet * conf = ksNew (0, KS_END);
	PLUGIN_OPEN ("file");

	KeySet * ks = ksNew (0, KS_END);

	succeed_if (plugin->kdbGet (plugin, ks, parentKey) >= 1, "call to kdbGet was not successful");

	keySetString (parentKey, elektraFilename ());

	succeed_if (plugin->kdbSet (plugin, ks, parentKey) == 1, "call to kdbSet was not successful");

	succeed_if (compare_line_files (srcdir_file (fileName), keyString (parentKey)), "files do not match as expected");

	ksDel (ks);
	keyDel (parentKey);

	PLUGIN_CLOSE ();
}
예제 #16
0
static void test_file_signature_operations (void)
{
	Plugin * plugin = NULL;
	Key * parentKey = keyNew ("system", KEY_END);
	KeySet * modules = ksNew (0, KS_END);
	KeySet * config = newPluginConfiguration ();

	elektraModulesInit (modules, 0);
	plugin = elektraPluginOpen (PLUGIN_NAME, modules, config, 0);
	succeed_if (plugin, "failed to open plugin handle");
	if (plugin)
	{
		KeySet * data = ksNew (0, KS_END);
		const char * tmpFile = elektraFilename ();
		if (tmpFile)
		{
			// prepare test file to be encrypted
			writeTestFile (tmpFile);
			keySetString (parentKey, tmpFile);

			// try to encrypt the file
			succeed_if (plugin->kdbSet (plugin, data, parentKey) == 1, "kdb set failed");
			succeed_if (isTestFileCorrect (tmpFile) == -1, "file content did not change during encryption");

			// try to decrypt/verify the file
			succeed_if (plugin->kdbGet (plugin, data, parentKey) == 1, "kdb get failed");

			remove (tmpFile);
		}

		ksDel (data);
		elektraPluginClose (plugin, 0);
	}

	elektraModulesClose (modules, 0);
	ksDel (modules);
	keyDel (parentKey);
}
예제 #17
0
static void test_BlockresolverWrite (char * fileName, char * compareName)
{
	FILE * fin = fopen (srcdir_file (fileName), "r");
	char buffer[1024];
	const char * foutname = elektraFilename ();
	FILE * fout = fopen (foutname, "w");
	while (fgets (buffer, sizeof (buffer), fin))
	{
		fputs (buffer, fout);
	}
	fclose (fin);
	fclose (fout);

	Key * parentKey = keyNew ("system/test/blockresolver-write", KEY_VALUE, foutname, KEY_END);
	KeySet * conf = ksNew (10, keyNew ("system/path", KEY_VALUE, foutname, KEY_END),
			       keyNew ("system/identifier", KEY_VALUE, "### block config", KEY_END), KS_END);
	KeySet * modules = ksNew (0, KS_END);
	KeySet * ks = ksNew (0, KS_END);
	elektraModulesInit (modules, 0);
	Plugin * resolver = elektraPluginOpen ("blockresolver", modules, ksDup (conf), 0);
	succeed_if (resolver->kdbGet (resolver, ks, parentKey) >= 0, "blockresolver->kdbGet failed");
	Plugin * storage = elektraPluginOpen ("ini", modules, ksNew (0, KS_END), 0);
	succeed_if (storage->kdbGet (storage, ks, parentKey) >= 0, "storage->kdbGet failed");
	keySetString (ksLookupByName (ks, "system/test/blockresolver-write/section/key", 0), "only the inside has changed");
	succeed_if (storage->kdbSet (storage, ks, parentKey) >= 0, "storage->kdbSet failed");
	succeed_if (resolver->kdbSet (resolver, ks, parentKey) >= 0, "blockresolver->kdbSet failed");
	succeed_if (resolver->kdbSet (resolver, ks, parentKey) >= 0, "blockresolver->kdbSet failed");

	succeed_if (compare_line_files (srcdir_file (compareName), foutname), "files do not match as expected");

	elektraPluginClose (storage, 0);
	elektraPluginClose (resolver, 0);
	ksDel (conf);
	ksDel (ks);
	elektraModulesClose (modules, 0);
	ksDel (modules);
	keyDel (parentKey);
}
예제 #18
0
/**
 * Creates a new Elektra key from the specified Augeas key.
 * If any step during key conversion fails, an error is returned
 * in order to prevent inconsistent keys.
 */
static int convertToKey (augeas * handle, const char * treePath, void * data)
{
	struct KeyConversion * conversionData = (struct KeyConversion *)data;
	int result = 0;
	const char * value = 0;
	result = aug_get (handle, treePath, &value);

	/* we were unable to retrieve the augeas value */
	if (result < 0) return result;

	Key * key = createKeyFromPath (conversionData->parentKey, treePath);

	/* fill key values */
	keySetString (key, value);
	conversionData->currentOrder++;
	result = keySetOrderMeta (key, conversionData->currentOrder);

	/* setting the correct key order failed */
	if (result < 0) return result;

	result = ksAppendKey (conversionData->ks, key);

	return result;
}
예제 #19
0
static void test_intNoUpdateWithInvalidValue (void)
{
	printf ("test no update with invalid value\n");

	KeySet * conf = ksNew (0, KS_END);
	PLUGIN_OPEN ("internalnotification");

	Key * valueKey = keyNew ("user/test/internalnotification/value", KEY_END);
	KeySet * ks = ksNew (1, valueKey, KS_END);

	int value = 123;
	succeed_if (internalnotificationRegisterInt (plugin, valueKey, &value) == 1,
		    "call to elektraInternalnotificationRegisterInt was not successful");

	keySetString (valueKey, "42abcd");


	elektraInternalnotificationUpdateRegisteredKeys (plugin, ks);

	succeed_if (value == 123, "registered value was updated");

	ksDel (ks);
	PLUGIN_CLOSE ();
}
예제 #20
0
파일: iconv.c 프로젝트: KurtMi/libelektra
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 */
}
예제 #21
0
static CondResult parseConditionString (const Key * meta, const Key * suffixList, Key * parentKey, Key * key, KeySet * ks, Operation op)
{
	const char * conditionString = keyString (meta);
	const char * regexString1 = "(\\(((.*)?)\\))[[:space:]]*\\?";
	const char * regexString2 = "\\?[[:space:]]*(\\(((.*)?)\\))";
	const char * regexString3 = "[[:space:]]*:[[:space:]]*(\\(((.*)?)\\))";
	regex_t regex1, regex2, regex3;
	CondResult ret;
	if ((ret = regcomp (&regex1, regexString1, REGEX_FLAGS_CONDITION)))
	{
		ELEKTRA_SET_ERROR (87, parentKey, "Couldn't compile regex: most likely out of memory"); // the regex compiles so the only
		// possible error would be out of
		// memory
		ksDel (ks);
		return ERROR;
	}
	if ((ret = regcomp (&regex2, regexString2, REGEX_FLAGS_CONDITION)))
	{
		ELEKTRA_SET_ERROR (87, parentKey, "Couldn't compile regex: most likely out of memory"); // the regex compiles so the only
		// possible error would be out of
		// memory
		regfree (&regex1);
		ksDel (ks);
		return ERROR;
	}
	if ((ret = regcomp (&regex3, regexString3, REGEX_FLAGS_CONDITION)))
	{
		ELEKTRA_SET_ERROR (87, parentKey, "Couldn't compile regex: most likely out of memory"); // the regex compiles so the only
		// possible error would be out of
		// memory
		regfree (&regex1);
		regfree (&regex2);
		ksDel (ks);
		return ERROR;
	}
	int subMatches = 6;
	regmatch_t m[subMatches];
	int nomatch = regexec (&regex1, conditionString, subMatches, m, 0);
	if (nomatch)
	{
		ELEKTRA_SET_ERRORF (134, parentKey, "Invalid syntax: \"%s\". Check kdb info conditionals for additional information",
				    conditionString);
		regfree (&regex1);
		regfree (&regex2);
		regfree (&regex3);
		ksDel (ks);
		return ERROR;
	}
	if (m[1].rm_so == -1)
	{
		ELEKTRA_SET_ERRORF (134, parentKey, "Invalid syntax: \"%s\". Check kdb info conditionals for additional information",
				    conditionString);
		regfree (&regex1);
		regfree (&regex2);
		regfree (&regex3);
		ksDel (ks);
		return ERROR;
	}
	int startPos = m[1].rm_so;
	int endPos = m[1].rm_eo;
	char * condition = elektraMalloc (endPos - startPos + 1);
	char * thenexpr = NULL;
	char * elseexpr = NULL;
	strncpy (condition, conditionString + startPos, endPos - startPos);
	condition[endPos - startPos] = '\0';
	nomatch = regexec (&regex2, conditionString, subMatches, m, 0);
	if (nomatch)
	{
		ELEKTRA_SET_ERRORF (134, parentKey, "Invalid syntax: \"%s\". Check kdb info conditionals for additional information",
				    conditionString);
		regfree (&regex1);
		regfree (&regex2);
		regfree (&regex3);
		ksDel (ks);
		return ERROR;
	}
	if (m[1].rm_so == -1)
	{
		ELEKTRA_SET_ERRORF (134, parentKey, "Invalid syntax: \"%s\". Check kdb info conditionals for additional information",
				    conditionString);
		regfree (&regex1);
		regfree (&regex2);
		regfree (&regex3);
		ksDel (ks);
		return ERROR;
	}

	startPos = m[1].rm_so;
	endPos = m[1].rm_eo;
	thenexpr = elektraMalloc (endPos - startPos + 1);
	strncpy (thenexpr, conditionString + startPos, endPos - startPos);
	thenexpr[endPos - startPos] = '\0';

	nomatch = regexec (&regex3, conditionString, subMatches, m, 0);
	if (!nomatch)
	{
		if (m[1].rm_so == -1)
		{
			ELEKTRA_SET_ERRORF (134, parentKey,
					    "Invalid syntax: \"%s\". Check kdb info conditionals for additional information",
					    conditionString);
			regfree (&regex1);
			regfree (&regex2);
			regfree (&regex3);
			ksDel (ks);
			return ERROR;
		}
		thenexpr[strlen (thenexpr) - ((m[0].rm_eo - m[0].rm_so))] = '\0';
		startPos = m[1].rm_so;
		endPos = m[1].rm_eo;
		elseexpr = elektraMalloc (endPos - startPos + 1);
		strncpy (elseexpr, conditionString + startPos, endPos - startPos);
		elseexpr[endPos - startPos] = '\0';
	}

	ret = parseCondition (key, condition, suffixList, ks, parentKey);
	if (ret == TRUE)
	{
		if (op == ASSIGN)
		{
			const char * assign = isAssign (key, thenexpr, parentKey, ks);
			if (assign != NULL)
			{
				keySetString (key, assign);
				ret = TRUE;
				goto CleanUp;
			}
			else
			{
				ret = ERROR;
				goto CleanUp;
			}
		}
		else
		{
			ret = parseCondition (key, thenexpr, suffixList, ks, parentKey);
			if (ret == FALSE)
			{
				ELEKTRA_SET_ERRORF (135, parentKey, "Validation of Key %s: %s failed. (%s failed)",
						    keyName (key) + strlen (keyName (parentKey)) + 1, conditionString, thenexpr);
			}
			else if (ret == ERROR)
			{
				ELEKTRA_SET_ERRORF (134, parentKey,
						    "Invalid syntax: \"%s\". Check kdb info conditionals for additional information",
						    thenexpr);
			}
		}
	}
	else if (ret == FALSE)
	{
		if (elseexpr)
		{
			if (op == ASSIGN)
			{
				const char * assign = isAssign (key, elseexpr, parentKey, ks);
				if (assign != NULL)
				{
					keySetString (key, assign);
					ret = TRUE;
					goto CleanUp;
				}
				else
				{
					ret = ERROR;
					goto CleanUp;
				}
			}
			else
			{
				ret = parseCondition (key, elseexpr, suffixList, ks, parentKey);

				if (ret == FALSE)
				{
					ELEKTRA_SET_ERRORF (135, parentKey, "Validation of Key %s: %s failed. (%s failed)",
							    keyName (key) + strlen (keyName (parentKey)) + 1, conditionString, elseexpr);
				}
				else if (ret == ERROR)
				{
					ELEKTRA_SET_ERRORF (
						134, parentKey,
						"Invalid syntax: \"%s\". Check kdb info conditionals for additional information", elseexpr);
				}
			}
		}
		else
		{
			ret = NOEXPR;
		}
	}
	else if (ret == ERROR)
	{
		ELEKTRA_SET_ERRORF (134, parentKey, "Invalid syntax: \"%s\". Check kdb info conditionals for additional information",
				    condition);
	}

CleanUp:
	elektraFree (condition);
	elektraFree (thenexpr);
	if (elseexpr) elektraFree (elseexpr);
	regfree (&regex1);
	regfree (&regex2);
	regfree (&regex3);
	ksDel (ks);
	return ret;
}
예제 #22
0
static CondResult evalCondition (const Key * curKey, const char * leftSide, Comparator cmpOp, const char * rightSide,
				 const char * condition, const Key * suffixList, KeySet * ks, Key * parentKey)
{
	char * lookupName = NULL;
	char * compareTo = NULL;
	Key * key;
	int len;
	long result = 0;
	if (rightSide)
	{
		if (rightSide[0] == '\'')
		{
			// right side of the statement is a literal enclosed by ''
			char * endPos = strchr (rightSide + 1, '\'');
			if (!endPos)
			{
				result = ERROR;
				goto Cleanup;
			}
			if (elektraRealloc ((void **) &compareTo, endPos - rightSide) < 0)
			{
				ELEKTRA_SET_ERROR (87, parentKey, "Out of memory");
				result = ERROR;
				goto Cleanup;
			}
			memset (compareTo, 0, endPos - rightSide);
			strncat (compareTo, rightSide + 1, endPos - rightSide - 1);
		}
		else if (rightSide && elektraStrLen (rightSide) > 1)
		{
			// not a literal, it has to be a key
			if (rightSide[0] == '@')
				len = keyGetNameSize (parentKey) + elektraStrLen (rightSide);
			else if (!strncmp (rightSide, "..", 2) || (rightSide[0] == '.'))
				len = keyGetNameSize (curKey) + elektraStrLen (rightSide);
			else
				len = elektraStrLen (rightSide);

			if (elektraRealloc ((void **) &lookupName, len) < 0)
			{
				ELEKTRA_SET_ERROR (87, parentKey, "Out of memory");
				result = ERROR;
				goto Cleanup;
			}
			if (rightSide[0] == '@')
				snprintf (lookupName, len, "%s/%s", keyName (parentKey), rightSide + 1);
			else if (rightSide[0] == '.') // either starts with . or .., doesn't matter at this point
				snprintf (lookupName, len, "%s/%s", keyName (curKey), rightSide);
			else
				snprintf (lookupName, len, "%s", rightSide);

			key = ksLookupByName (ks, lookupName, 0);
			if (!key)
			{
				if (!keyGetMeta (parentKey, "error"))
				{
					ELEKTRA_SET_ERRORF (133, parentKey, "Key %s not found but is required for the evaluation of %s",
							    lookupName, condition);
				}
				result = FALSE;
				goto Cleanup;
			}
			if (elektraRealloc ((void **) &compareTo, keyGetValueSize (key)) < 0)
			{
				ELEKTRA_SET_ERROR (87, parentKey, "Out of memory");
				result = ERROR;
				goto Cleanup;
			}
			strcpy (compareTo, keyString (key));
		}
	}
	if (leftSide[0] == '@')
		len = keyGetNameSize (parentKey) + elektraStrLen (leftSide);
	else if (!strncmp (leftSide, "..", 2) || (leftSide[0] == '.'))
		len = keyGetNameSize (curKey) + elektraStrLen (leftSide);
	else
		len = elektraStrLen (leftSide);

	if (elektraRealloc ((void **) &lookupName, len) < 0)
	{
		ELEKTRA_SET_ERROR (87, parentKey, "Out of memory");
		result = ERROR;
		goto Cleanup;
	}
	if (leftSide[0] == '@')
		snprintf (lookupName, len, "%s/%s", keyName (parentKey), leftSide + 1);
	else if (leftSide[0] == '.') // either . or .., doesn't matter here
		snprintf (lookupName, len, "%s/%s", keyName (curKey), leftSide);
	else
		snprintf (lookupName, len, "%s", leftSide);
	key = ksLookupByName (ks, lookupName, 0);
	if (cmpOp == NEX)
	{
		if (key)
			result = FALSE;
		else
			result = TRUE;
		goto Cleanup;
	}
	if (!key && cmpOp != OR && cmpOp != AND)
	{
		if (!keyGetMeta (parentKey, "error"))
		{
			ELEKTRA_SET_ERRORF (133, parentKey, "Key %s not found but is required for the evaluation of %s", lookupName,
					    condition);
		}
		result = FALSE;
		goto Cleanup;
	}
	long ret;
	if (cmpOp == OR || cmpOp == AND)
		ret = compareStrings (leftSide, rightSide, NULL);
	else
		ret = compareStrings (keyString (key), compareTo, suffixList);
	switch (cmpOp)
	{
	case EQU:
		if (!ret) result = TRUE;
		break;
	case NOT:
		if (ret) result = TRUE;
		break;
	case LT:
		if (ret < 0) result = TRUE;
		break;
	case LE:
		if (ret <= 0) result = TRUE;
		break;
	case GT:
		if (ret > 0) result = TRUE;
		break;
	case GE:
		if (ret >= 0) result = TRUE;
		break;
	case SET:
		keySetString (key, compareTo);
		result = TRUE;
		break;
	case AND:
		if (ret == 0 && !strcmp (leftSide, "'1'")) result = TRUE;
		break;
	case OR:
		if (!strcmp (leftSide, "'1'") || (rightSide && !strcmp (rightSide, "'1'"))) result = TRUE;
		break;
	default:
		result = ERROR;
		break;
	}
// freeing allocated heap
Cleanup:
	if (lookupName) elektraFree (lookupName);
	if (compareTo) elektraFree (compareTo);
	return result;
}
예제 #23
0
static void test_endings()
{
	printf ("Test endings trie\n");

	for (int i=0; i<4; ++i)
	{

	Trie *trie = 0;
	switch (i)
	{
	case 0:
		trie = test_insert (trie, "user/endings/","slash");
		trie = test_insert (trie, "user/endings#","hash");
		trie = test_insert (trie, "user/endings ","space");
		trie = test_insert (trie, "user/endings\200","endings");
		break;
	case 1:
		trie = test_insert (trie, "user/endings#","hash");
		trie = test_insert (trie, "user/endings ","space");
		trie = test_insert (trie, "user/endings\200","endings");
		trie = test_insert (trie, "user/endings/","slash");
		break;
	case 2:
		trie = test_insert (trie, "user/endings ","space");
		trie = test_insert (trie, "user/endings\200","endings");
		trie = test_insert (trie, "user/endings/","slash");
		trie = test_insert (trie, "user/endings#","hash");
		break;
	case 3:
		trie = test_insert (trie, "user/endings\200","endings");
		trie = test_insert (trie, "user/endings ","space");
		trie = test_insert (trie, "user/endings#","hash");
		trie = test_insert (trie, "user/endings/","slash");
		break;
	}

	exit_if_fail (trie, "trie was not build up successfully");

	Key *searchKey = keyNew("user", KEY_END);
	Backend *backend = elektraTrieLookup(trie, searchKey);
	succeed_if (!backend, "there should be no backend");


	Key *mp = keyNew("user/endings", KEY_VALUE, "slash", KEY_END);
	keySetName(searchKey, "user/endings");
	backend = elektraTrieLookup(trie, searchKey);
	succeed_if (backend, "there should be a backend");
	compare_key(backend->mountpoint, mp);


	keySetName(searchKey, "user/endings#");
	keySetName(mp, "user/endings#");
	keySetString(mp, "hash");
	Backend *b2 = elektraTrieLookup(trie, searchKey);
	succeed_if (b2, "there should be a backend");
	succeed_if (backend != b2, "should be other backend");
	compare_key(b2->mountpoint, mp);


	keySetName(searchKey, "user/endings/_");
	keySetName(mp, "user/endings");
	keySetString(mp, "slash");
	b2 = elektraTrieLookup(trie, searchKey);
	succeed_if (b2, "there should be a backend");
	succeed_if (backend == b2, "should be the same backend");
	compare_key(b2->mountpoint, mp);


	keySetName(searchKey, "user/endings/X");
	keySetName(mp, "user/endings");
	keySetString(mp, "slash");
	b2 = elektraTrieLookup(trie, searchKey);
	succeed_if (b2, "there should be a backend");
	succeed_if (backend == b2, "should be the same backend");
	compare_key(b2->mountpoint, mp);


	keySetName(searchKey, "user/endings_");
	b2 = elektraTrieLookup(trie, searchKey);
	succeed_if (!b2, "there should be no backend");


	keySetName(searchKey, "user/endingsX");
	b2 = elektraTrieLookup(trie, searchKey);
	succeed_if (!b2, "there should be no backend");


	keySetName(searchKey, "user/endings!");
	b2 = elektraTrieLookup(trie, searchKey);
	succeed_if (!b2, "there should be no backend");


	keySetName(searchKey, "user/endings ");
	keySetName(mp, "user/endings ");
	keySetString(mp, "space");
	b2 = elektraTrieLookup(trie, searchKey);
	succeed_if (b2, "there should be a backend");
	succeed_if (backend != b2, "should be other backend");
	compare_key(b2->mountpoint, mp);

	keySetName(searchKey, "user/endings\200");
	keySetName(mp, "user/endings\200");
	keySetString(mp, "endings");
	b2 = elektraTrieLookup(trie, searchKey);
	succeed_if (b2, "there should be a backend");
	succeed_if (backend != b2, "should be other backend");
	compare_key(b2->mountpoint, mp);

	// output_trie(trie);

	elektraTrieClose(trie, 0);
	keyDel (mp);
	keyDel (searchKey);

	}
}
예제 #24
0
/** Call a plugin's function in a child process
 *
 * This will wrap all the required information to execute the given
 * command in a keyset and send it over to the child process. Then
 * it waits for the child process's answer and copies the result
 * back into the original plugin keyset and plugin key.
 *
 * Typically called like
 * @code
int elektraPluginSet (Plugin * handle, KeySet * returned, Key * parentKey)
{
	ElektraPluginProcess * pp = elektraPluginGetData (handle);
	if (elektraPluginProcessIsParent (pp)) return elektraPluginProcessSend (pp, ELEKTRA_PLUGINPROCESS_SET, returned, parentKey);

	// actual plugin functionality to be executed in a child process
	return ELEKTRA_PLUGIN_STATUS_SUCCESS;
}
 * @endcode
 *
 * @param pp the data structure containing the plugin's process information
 * @param command the plugin command that should be executed, e.g. ELEKTRA_PLUGINPROCESS_GET
 * @param originalKeySet the original key set that the parent process receives
 * @param key the original key the parent process receives
 * @retval ELEKTRA_PLUGIN_STATUS_ERROR if the child process communication failed
 * @retval the called plugin's return value otherwise
 * @see elektraPluginProcessIsParent for checking if we are in the parent or child process
 * @ingroup processplugin
 **/
int elektraPluginProcessSend (const ElektraPluginProcess * pp, pluginprocess_t command, KeySet * originalKeySet, Key * key)
{
	// Ensure we have a keyset when trying to call GET SET and ERROR
	if ((command == ELEKTRA_PLUGINPROCESS_GET || command == ELEKTRA_PLUGINPROCESS_SET || command == ELEKTRA_PLUGINPROCESS_ERROR) &&
	    originalKeySet == NULL)
	{
		ELEKTRA_SET_ERROR (191, key,
				   "originalKeySet has to exist when calling GET SET and ERROR via pluginprocess; but it is NULL");
		return ELEKTRA_PLUGIN_STATUS_ERROR;
	}

	// Construct the command set that controls the pluginprocess communication
	KeySet * commandKeySet = ksNew (6, KS_END);
	ksAppendKey (commandKeySet, keyNew ("/pluginprocess/parent/name", KEY_VALUE, keyName (key), KEY_END));
	Key * parentKey = keyDup (key);
	keySetName (parentKey, "/pluginprocess/parent");
	ksAppendKey (commandKeySet, parentKey);
	char * commandStr = longToStr (command);
	ksAppendKey (commandKeySet, keyNew ("/pluginprocess/command", KEY_VALUE, commandStr, KEY_END));
	elektraFree (commandStr);
	ksAppendKey (commandKeySet, keyNew ("/pluginprocess/version", KEY_VALUE, "1", KEY_END));

	// Some plugin functions don't use keysets, in that case don't send any actual payload, signal via flag
	KeySet * keySet = originalKeySet != NULL ? ksDup (originalKeySet) : NULL;
	char * payloadSizeStr = longToStr (ksGetSize (originalKeySet));
	ksAppendKey (commandKeySet,
		     keyNew ("/pluginprocess/payload/size", KEY_VALUE, originalKeySet == NULL ? "-1" : payloadSizeStr, KEY_END));
	elektraFree (payloadSizeStr);

	// Serialize, currently statically use dump as our default format, this already writes everything out to the pipe
	ELEKTRA_LOG ("Parent: Sending data to issue command %u it through pipe %s", command, keyString (pp->parentCommandPipeKey));
	elektraInvoke2Args (pp->dump, "set", commandKeySet, pp->parentCommandPipeKey);
	if (keySet != NULL)
	{
		ELEKTRA_LOG ("Parent: Sending the payload keyset with %zd keys through the pipe %s", ksGetSize (keySet),
			     keyString (pp->parentPayloadPipeKey));
		elektraInvoke2Args (pp->dump, "set", keySet, pp->parentPayloadPipeKey);
	}

	// Deserialize
	ELEKTRA_LOG_DEBUG ("Parent: Waiting for the result now on pipe %s", keyString (pp->childCommandPipeKey));
	elektraInvoke2Args (pp->dump, "get", commandKeySet, pp->childCommandPipeKey);

	if (keySet != NULL)
	{
		// clear the keyset before to avoid memleaks caused by dump
		char * endPtr;
		int prevErrno = errno;
		errno = 0;
		long payloadSize =
			strtol (keyString (ksLookupByName (commandKeySet, "/pluginprocess/payload/size", KDB_O_NONE)), &endPtr, 10);
		// in case the payload size fails to be transferred, that it shouldn't, we simply assume the previous size
		if (*endPtr != '\0' || errno == ERANGE || payloadSize < 0) payloadSize = ksGetSize (keySet);
		errno = prevErrno;
		ksDel (keySet);
		keySet = ksNew (payloadSize, KS_END);
		elektraInvoke2Args (pp->dump, "get", keySet, pp->childPayloadPipeKey);
		ELEKTRA_LOG ("Parent: We received %zd keys in return", ksGetSize (keySet));
	}

	// Bring everything back in order by removing our process-related keys
	Key * parentDeserializedKey = ksLookupByName (commandKeySet, "/pluginprocess/parent", KDB_O_NONE);
	Key * resultKey = ksLookupByName (commandKeySet, "/pluginprocess/result", KDB_O_NONE);

	// Parse the result value
	char * endPtr;
	int prevErrno = errno;
	errno = 0;
	long lresult = strtol (keyString (resultKey), &endPtr, 10);
	if (*endPtr != '\0' || errno == ERANGE || lresult > INT_MAX || lresult < INT_MIN)
	{
		ELEKTRA_SET_ERRORF (191, key, "Received invalid return code or no KeySet: %s", keyString (resultKey));
		lresult = ELEKTRA_PLUGIN_STATUS_ERROR;
	}
	else // Copy everything back into the actual keysets
	{
		Key * parentKeyInOriginalKeySet = keySet != NULL ? ksLookup (originalKeySet, key, KDB_O_NONE) : NULL;
		// maybe there are just 2 keys with the same name, can happen in theory, so compare memory
		int parentKeyExistsInOriginalKeySet = parentKeyInOriginalKeySet == key;
		// if the child added the parent key to the keyset pop it from the keyset
		// then reinsert key after we copied the data and delete this serialized copy
		Key * parentKeyInKeySet = keySet != NULL ? ksLookup (keySet, key, KDB_O_POP) : NULL;
		int childAddedParentKey = parentKeyInKeySet != NULL;

		// Unfortunately we can't use keyCopy here as ksAppendKey locks it so it will fail
		// This is the case if the parent key is also contained in the originalKeySet / has been appended
		// As an invariant we assume plugins don't change the parent key's name during a plugin call
		// This would interfere with keyset memberships
		keySetString (key, keyString (parentDeserializedKey));

		// Clear metadata before, we allow children to modify it
		keyRewindMeta (key);
		const Key * currentMeta;
		while ((currentMeta = keyNextMeta (key)) != NULL)
		{
			keySetMeta (key, keyName (currentMeta), 0);
		}
		keyCopyAllMeta (key, parentDeserializedKey);
		if (childAddedParentKey) keyCopyAllMeta (key, parentKeyInKeySet);

		if (keySet != NULL)
		{
			// in case originalKeySet contains key this would make it stuck
			// thus remove it here and re-add it afterwards
			if (parentKeyExistsInOriginalKeySet) ksLookup (originalKeySet, parentKeyInOriginalKeySet, KDB_O_POP);
			ksCopy (originalKeySet, keySet);
			if (parentKeyExistsInOriginalKeySet || childAddedParentKey) ksAppendKey (originalKeySet, key);
			if (childAddedParentKey) keyDel (parentKeyInKeySet);
		}
	}
	errno = prevErrno;

	// Command finished, cleanup the remaining memory now
	ksDel (commandKeySet);
	if (keySet != NULL) ksDel (keySet);

	return lresult; // Safe, we had a bound check before, and plugins should return values in the int range
}
예제 #25
0
/** Start the child process' command loop
 *
 * This will make the child process wait for plugin commands
 * and execute them, returning the result to the parent. This
 * is typically called in a plugin's open function.
 *
 * @param handle the plugin's handle
 * @param pp the data structure containing the plugin's process information
 * @see elektraPluginProcessInit how to use this function in a plugin
 * @ingroup processplugin
 **/
void elektraPluginProcessStart (Plugin * handle, ElektraPluginProcess * pp)
{
	int counter = 0;

	do
	{
		KeySet * commandKeySet = ksNew (6, KS_END);
		KeySet * keySet = NULL;
		ELEKTRA_LOG_DEBUG ("Child: Wait for commands on pipe %s", keyString (pp->parentCommandPipeKey));
		elektraInvoke2Args (pp->dump, "get", commandKeySet, pp->parentCommandPipeKey);

		if (ksGetSize (commandKeySet) == 0)
		{
			ELEKTRA_LOG_DEBUG ("Child: Failed to read from parentCommandPipe, exiting");
			ksDel (commandKeySet);
			break;
		}

		Key * payloadSizeKey = ksLookupByName (commandKeySet, "/pluginprocess/payload/size", KDB_O_NONE);
		char * endPtr;
		// We'll always write some int value into it, so this should be fine
		int prevErrno = errno;
		errno = 0;
		long payloadSize = strtol (keyString (payloadSizeKey), &endPtr, 10);
		// in case the payload size fails to be transferred, that it shouldn't, we can only assume no payload
		if (*endPtr == '\0' && errno != ERANGE && payloadSize >= 0)
		{
			keySet = ksNew (payloadSize, KS_END);
			elektraInvoke2Args (pp->dump, "get", keySet, pp->parentPayloadPipeKey);
			ELEKTRA_LOG_DEBUG ("Child: We received a KeySet with %zd keys in it", ksGetSize (keySet));
		}
		errno = prevErrno;

		Key * commandKey = ksLookupByName (commandKeySet, "/pluginprocess/command", KDB_O_NONE);
		Key * parentNameKey = ksLookupByName (commandKeySet, "/pluginprocess/parent/name", KDB_O_NONE);
		Key * parentKey = ksLookupByName (commandKeySet, "/pluginprocess/parent", KDB_O_POP);
		Key * key = keyDup (parentKey);
		keySetName (key, keyString (parentNameKey));
		int result = ELEKTRA_PLUGIN_STATUS_ERROR;

		// We'll always write some int value into it, so this should be fine
		prevErrno = errno;
		errno = 0;
		long command = strtol (keyString (commandKey), &endPtr, 10);
		if (*endPtr == '\0' && errno != ERANGE)
		{
			ELEKTRA_LOG ("Child: We want to execute the command with the value %ld now", command);
			// Its hard to figure out the enum size in a portable way but for this comparison it should be ok
			switch (command)
			{
			case ELEKTRA_PLUGINPROCESS_OPEN:
				counter++;
				result = handle->kdbOpen (handle, key);
				break;
			case ELEKTRA_PLUGINPROCESS_CLOSE:
				counter--;
				result = handle->kdbClose (handle, key);
				break;
			case ELEKTRA_PLUGINPROCESS_GET:
				result = handle->kdbGet (handle, keySet, key);
				break;
			case ELEKTRA_PLUGINPROCESS_SET:
				result = handle->kdbSet (handle, keySet, key);
				break;
			case ELEKTRA_PLUGINPROCESS_ERROR:
				result = handle->kdbError (handle, keySet, key);
				break;
			default:
				result = ELEKTRA_PLUGIN_STATUS_ERROR;
			}
			ELEKTRA_LOG_DEBUG ("Child: Command executed with return value %d", result);
		}
		else
		{
			ELEKTRA_LOG_DEBUG ("Child: Unrecognized command %s", keyString (commandKey));
			ELEKTRA_SET_ERRORF (191, key, "Received invalid command code or no KeySet: %s", keyString (commandKey));
		}
		errno = prevErrno;
		char * resultStr = longToStr (result);
		ksAppendKey (commandKeySet, keyNew ("/pluginprocess/result", KEY_VALUE, resultStr, KEY_END));
		elektraFree (resultStr);
		keySetName (key, "/pluginprocess/parent");
		ksAppendKey (commandKeySet, key);
		keyDel (parentKey);

		ELEKTRA_LOG_DEBUG ("Child: Writing the results back to the parent");
		elektraInvoke2Args (pp->dump, "set", commandKeySet, pp->childCommandPipeKey);
		if (keySet != NULL)
		{
			char * resultPayloadSize = longToStr (ksGetSize (keySet));
			keySetString (payloadSizeKey, resultPayloadSize);
			elektraFree (resultPayloadSize);
			elektraInvoke2Args (pp->dump, "set", keySet, pp->childPayloadPipeKey);
			ksDel (keySet);
		}
		ksDel (commandKeySet);
		ELEKTRA_LOG ("Child: Command handled, startup counter is at %d", counter);
	} while (counter);

	// Final Cleanup
	ELEKTRA_LOG_DEBUG ("Child: All done, exiting the child process now");
	cleanupPluginData (pp, 0, 1);
	// All done, exit the child process so it won't do any actual effects in elektra
	_Exit (EXIT_SUCCESS);
}
예제 #26
0
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;
}
static void test_default()
{
	printf ("Test mounting with default\n");

	KDB *kdb = kdb_new();
	Key *errorKey = keyNew(0);
	KeySet *modules = modules_config();
	succeed_if (elektraMountOpen(kdb, root_config(), modules, errorKey) == 0, "could not buildup mount");
	succeed_if (elektraMountDefault(kdb, modules, errorKey) == 0, "could not mount default backend");

	succeed_if (kdb->split->size == 6, "size of split not correct");
	Key *mp = keyNew("spec", KEY_VALUE, "root", KEY_END);
	compare_key(mp, kdb->split->parents[0]);
	keySetName(mp, "dir"); keySetString (mp, "root");
	compare_key(mp, kdb->split->parents[1]);
	keySetName(mp, "user"); keySetString (mp, "root");
	compare_key(mp, kdb->split->parents[2]);
	keySetName(mp, "system"); keySetString (mp, "root");
	compare_key(mp, kdb->split->parents[3]);
	keySetName(mp, "system/elektra"); keySetString (mp, "default");
	compare_key(mp, kdb->split->parents[5]);

	// must be last, needed later
	keySetName(mp, "user/tests/simple"); keySetString (mp, "simple");
	compare_key(mp, kdb->split->parents[4]);

	succeed_if(output_warnings (errorKey), "warnings found");
	succeed_if(output_error (errorKey), "error found");

	exit_if_fail (kdb->trie, "trie was not build up successfully");

	// output_trie (kdb->trie);

	Key *searchKey = keyNew("", KEY_END);
	Key *rmp = keyNew("", KEY_VALUE, "root", KEY_END);
	elektraKeySetName(rmp, "/", KEY_CASCADING_NAME);
	Backend *b2 = 0;

	keySetName (searchKey, "user");
	b2 = elektraTrieLookup(kdb->trie, searchKey);
	succeed_if (b2, "there should be a backend");
	compare_key(b2->mountpoint, rmp);


	Backend *backend = 0;
	keySetName(searchKey, "user/tests/simple");
	backend = elektraTrieLookup(kdb->trie, searchKey);
	succeed_if (backend, "there should be a backend");
	compare_key(backend->mountpoint, mp);


	keySetName(searchKey, "user/tests/simple/below");
	b2 = elektraTrieLookup(kdb->trie, searchKey);
	succeed_if (b2, "there should be a backend");
	succeed_if (backend == b2, "should be same backend");
	compare_key(b2->mountpoint, mp);


	keySetName(searchKey, "user/tests/simple/deep/below");
	b2 = elektraTrieLookup(kdb->trie, searchKey);
	succeed_if (b2, "there should be a backend");
	succeed_if (backend == b2, "should be same backend");
	compare_key(b2->mountpoint, mp);

	Key *dmp = keyNew ("", KEY_VALUE, "default", KEY_END);
	keySetName(searchKey, "system/elektra");
	b2 = elektraTrieLookup(kdb->trie, searchKey);
	succeed_if (b2, "there should be a backend");
	succeed_if (b2 == kdb->defaultBackend, "should be the default backend");
	compare_key(b2->mountpoint, dmp);

	keySetName(searchKey, "system/elektra/below");
	b2 = elektraTrieLookup(kdb->trie, searchKey);
	succeed_if (b2, "there should be a backend");
	succeed_if (b2 == kdb->defaultBackend, "should be the default backend");
	compare_key(b2->mountpoint, dmp);

	keyDel (dmp);
	keyDel (mp);
	keyDel (rmp);

	keyDel (searchKey);

	kdb_del (kdb);
	keyDel (errorKey);
	ksDel (modules);
}
static void test_modules()
{
	printf ("Test mounting with modules\n");

	KDB *kdb = kdb_new();
	Key *errorKey = keyNew(0);
	KeySet *modules = modules_config();
	succeed_if (elektraMountOpen(kdb, root_config(), modules, errorKey) == 0, "could not buildup mount");
	succeed_if (elektraMountDefault(kdb, modules, errorKey) == 0, "could not mount default backend");
	succeed_if (elektraMountModules(kdb, modules, errorKey) == 0, "could not mount modules");

	succeed_if(output_warnings (errorKey), "warnings found");
	succeed_if(output_error (errorKey), "error found");

	succeed_if (kdb->split->size == 8, "size of split not correct");
	Key *mp = keyNew("spec", KEY_VALUE, "root", KEY_END);
	compare_key(mp, kdb->split->parents[0]);
	keySetName(mp, "dir"); keySetString (mp, "root");
	compare_key(mp, kdb->split->parents[1]);
	keySetName(mp, "user"); keySetString (mp, "root");
	compare_key(mp, kdb->split->parents[2]);
	keySetName(mp, "system"); keySetString (mp, "root");
	compare_key(mp, kdb->split->parents[3]);
	/* we cannot exactly know where resolver+dump is located
	 *(depending on alphabet)
	keySetName(mp, "system/elektra/modules/"KDB_DEFAULT_RESOLVER); keySetString (mp, "modules");
	compare_key(mp, kdb->split->parents[4]);
	*/
	keySetName(mp, "system/elektra"); keySetString (mp, "default");
	compare_key(mp, kdb->split->parents[5]);

	keySetName(mp, "user/tests/simple"); keySetString (mp, "simple");
	compare_key(mp, kdb->split->parents[4]);

	exit_if_fail (kdb->trie, "trie was not build up successfully");

	// output_trie (kdb->trie);

	Key *searchKey = keyNew("", KEY_END);
	Key *rmp = keyNew("", KEY_VALUE, "root", KEY_END);
	elektraKeySetName(rmp, "/", KEY_CASCADING_NAME);
	Backend *b2 = 0;

	keySetName (searchKey, "user");
	b2 = elektraTrieLookup(kdb->trie, searchKey);
	succeed_if (b2, "there should be a backend");
	compare_key(b2->mountpoint, rmp);


	Backend *backend = 0;
	keySetName(searchKey, "user/tests/simple");
	backend = elektraTrieLookup(kdb->trie, searchKey);
	succeed_if (backend, "there should be a backend");
	compare_key(backend->mountpoint, mp);


	keySetName(searchKey, "user/tests/simple/below");
	b2 = elektraTrieLookup(kdb->trie, searchKey);
	succeed_if (b2, "there should be a backend");
	succeed_if (backend == b2, "should be same backend");
	compare_key(b2->mountpoint, mp);


	keySetName(searchKey, "user/tests/simple/deep/below");
	b2 = elektraTrieLookup(kdb->trie, searchKey);
	succeed_if (b2, "there should be a backend");
	succeed_if (backend == b2, "should be same backend");
	compare_key(b2->mountpoint, mp);

	Key *dmp = keyNew ("", KEY_VALUE, "default", KEY_END);
	keySetName(searchKey, "system/elektra");
	b2 = elektraTrieLookup(kdb->trie, searchKey);
	succeed_if (b2, "there should be a backend");
	succeed_if (b2 == kdb->defaultBackend, "should be the default backend");
	compare_key(b2->mountpoint, dmp);

	keySetName(searchKey, "system/elektra/below");
	b2 = elektraTrieLookup(kdb->trie, searchKey);
	succeed_if (b2, "there should be a backend");
	succeed_if (b2 == kdb->defaultBackend, "should be the default backend");
	compare_key(b2->mountpoint, dmp);

	Key *mmp = keyNew ("system/elektra/modules", KEY_VALUE, "modules", KEY_END);
	keyAddBaseName (mmp, "default");

	/*
	keySetName(searchKey, "system/elektra/modules/default");
	b2 = elektraTrieLookup(kdb->trie, searchKey);
	succeed_if (b2, "there should be a backend");
	succeed_if (b2 != kdb->defaultBackend, "should not be the default backend");
	compare_key(b2->mountpoint, mmp);
	*/

	keyDel (mmp);
	keyDel (dmp);
	keyDel (mp);
	keyDel (rmp);

	keyDel (searchKey);

	kdb_del (kdb);
	keyDel (errorKey);
	ksDel (modules);
}
예제 #29
0
/**
 * @brief decrypt the file specified at parentKey
 * @param pluginConfig holds the plugin configuration
 * @param parentKey holds the path to the file to be encrypted. Will hold an error description in case of failure.
 * @param state holds the plugin state
 * @retval 1 on success
 * @retval -1 on error, errorKey holds an error description
 */
static int fcryptDecrypt (KeySet * pluginConfig, Key * parentKey, fcryptState * state)
{
	int tmpFileFd = -1;
	char * tmpFile = getTemporaryFileName (pluginConfig, keyString (parentKey), &tmpFileFd);
	if (!tmpFile)
	{
		ELEKTRA_SET_ERROR (87, parentKey, "Memory allocation failed");
		return -1;
	}

	const size_t testMode = inTestMode (pluginConfig);

	// prepare argument vector for gpg call
	// 8 static arguments (magic number below) are:
	//   1. path to the binary
	//   2. --batch
	//   3. -o
	//   4. path to tmp file
	//   5. yes
	//   6. -d
	//   7. file to be encrypted
	//   8. NULL terminator
	int argc = 8 + (2 * testMode);
	char * argv[argc];
	int i = 0;

	argv[i++] = NULL;
	argv[i++] = "--batch";
	argv[i++] = "--yes";

	// if we are in test mode we add the trust model
	if (testMode)
	{
		argv[i++] = "--trust-model";
		argv[i++] = "always";
	}

	argv[i++] = "-o";
	argv[i++] = tmpFile;
	argv[i++] = "-d";
	// safely discarding const from keyString() return value
	argv[i++] = (char *) keyString (parentKey);
	argv[i++] = NULL;

	// NOTE the decryption process works like this:
	// gpg2 --batch --yes -o tmpfile -d configFile
	int result = ELEKTRA_PLUGIN_FUNCTION (gpgCall) (pluginConfig, parentKey, NULL, argv, argc);
	if (result == 1)
	{
		state->originalFilePath = elektraStrDup (keyString (parentKey));
		state->tmpFilePath = tmpFile;
		state->tmpFileFd = tmpFileFd;
		keySetString (parentKey, tmpFile);
	}
	else
	{
		// if anything went wrong above the temporary file is shredded and removed
		shredTemporaryFile (tmpFileFd, parentKey);
		if (unlink (tmpFile))
		{
			ELEKTRA_ADD_WARNINGF (ELEKTRA_WARNING_FCRYPT_UNLINK, parentKey, "Affected file: %s, error description: %s", tmpFile,
					      strerror (errno));
		}
		if (close (tmpFileFd))
		{
			ELEKTRA_ADD_WARNINGF (ELEKTRA_WARNING_FCRYPT_CLOSE, parentKey, "%s", strerror (errno));
		}
		elektraFree (tmpFile);
	}
	return result;
}
예제 #30
0
int elektraCryptoGcryDecrypt (elektraCryptoHandle * handle, Key * k, Key * errorKey)
{
	kdb_octet_t * value = (kdb_octet_t *)keyValue (k);
	const size_t valueLen = keyGetValueSize (k);

	kdb_octet_t * output;
	kdb_octet_t cipherBuffer[ELEKTRA_CRYPTO_GCRY_BLOCKSIZE];
	kdb_octet_t contentBuffer[ELEKTRA_CRYPTO_GCRY_BLOCKSIZE];
	kdb_unsigned_long_t written = 0;
	gcry_error_t gcry_err;

	// initialize crypto header data
	kdb_unsigned_long_t contentLen = 0;
	kdb_octet_t flags = ELEKTRA_CRYPTO_FLAG_NONE;

	// check if key has been encrypted in the first place
	const Key * metaEncrypted = keyGetMeta (k, ELEKTRA_CRYPTO_META_ENCRYPT);
	if (metaEncrypted == NULL || strlen (keyValue (metaEncrypted)) == 0)
	{
		// nothing to do
		return 1;
	}

	// plausibility check
	if (valueLen % ELEKTRA_CRYPTO_GCRY_BLOCKSIZE != 0)
	{
		ELEKTRA_SET_ERROR (ELEKTRA_ERROR_CRYPTO_DECRYPT_FAIL, errorKey, "value length is not a multiple of the block size");
		return (-1);
	}

	// prepare buffer for plain text output
	output = elektraMalloc (valueLen);
	if (output == NULL)
	{
		ELEKTRA_SET_ERROR (87, errorKey, "Memory allocation failed");
		return (-1);
	}

	// decrypt the header (1st block)
	memcpy (cipherBuffer, value, ELEKTRA_CRYPTO_GCRY_BLOCKSIZE);
	gcry_err = gcry_cipher_decrypt (*handle, contentBuffer, ELEKTRA_CRYPTO_GCRY_BLOCKSIZE, cipherBuffer, ELEKTRA_CRYPTO_GCRY_BLOCKSIZE);
	if (gcry_err != 0)
	{
		ELEKTRA_SET_ERRORF (ELEKTRA_ERROR_CRYPTO_DECRYPT_FAIL, errorKey, "Decryption failed because: %s", gcry_strerror (gcry_err));
		elektraFree (output);
		return (-1);
	}

	// restore the header data
	memcpy (&flags, contentBuffer, sizeof (flags));
	memcpy (&contentLen, contentBuffer + sizeof (flags), sizeof (contentLen));

	// decrypt content block by block
	// (i = start of the current block and the 1st block has already been consumed)
	for (kdb_unsigned_long_t i = ELEKTRA_CRYPTO_GCRY_BLOCKSIZE; i < valueLen; i += ELEKTRA_CRYPTO_GCRY_BLOCKSIZE)
	{
		memcpy (cipherBuffer, (value + i), ELEKTRA_CRYPTO_GCRY_BLOCKSIZE);
		gcry_err = gcry_cipher_decrypt (*handle, contentBuffer, ELEKTRA_CRYPTO_GCRY_BLOCKSIZE, cipherBuffer,
						ELEKTRA_CRYPTO_GCRY_BLOCKSIZE);
		if (gcry_err != 0)
		{
			ELEKTRA_SET_ERRORF (ELEKTRA_ERROR_CRYPTO_DECRYPT_FAIL, errorKey, "Decryption failed because: %s",
					    gcry_strerror (gcry_err));
			elektraFree (output);
			return (-1);
		}
		memcpy ((output + i - ELEKTRA_CRYPTO_GCRY_BLOCKSIZE), contentBuffer, ELEKTRA_CRYPTO_GCRY_BLOCKSIZE);
		written += ELEKTRA_CRYPTO_GCRY_BLOCKSIZE;
	}

	if (written < contentLen)
	{
		ELEKTRA_SET_ERROR (ELEKTRA_ERROR_CRYPTO_DECRYPT_FAIL, errorKey, "Content was shorter than described in the header");
		elektraFree (output);
		return (-1);
	}

	// write back the cipher text to the key
	if ((flags & ELEKTRA_CRYPTO_FLAG_STRING) == ELEKTRA_CRYPTO_FLAG_STRING)
	{
		keySetString (k, (const char *)output);
	}
	else if ((flags & ELEKTRA_CRYPTO_FLAG_NULL) == ELEKTRA_CRYPTO_FLAG_NULL || contentLen == 0)
	{
		keySetBinary (k, NULL, 0);
	}
	else
	{
		keySetBinary (k, output, contentLen);
	}

	elektraFree (output);
	return 1;
}