static void test_defaultonly()
{
	printf ("Test mounting with default only\n");

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


	// output_split (kdb->split);

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

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

	succeed_if (!kdb->trie, "trie should be empty");

	Key *searchKey = keyNew("", KEY_END);
	Backend *b2 = 0;

	keySetName (searchKey, "user");
	b2 = elektraTrieLookup(kdb->trie, searchKey);
	succeed_if (b2 == 0, "should be default backend");


	keySetName(searchKey, "user/tests/simple");
	b2 = elektraTrieLookup(kdb->trie, searchKey);
	succeed_if (b2 == 0, "should be default backend");


	keySetName(searchKey, "user/tests/simple/below");
	b2 = elektraTrieLookup(kdb->trie, searchKey);
	succeed_if (b2 == 0, "should be default backend");


	keySetName(searchKey, "user/tests/simple/deep/below");
	b2 = elektraTrieLookup(kdb->trie, searchKey);
	succeed_if (b2 == 0, "should be default backend");

	keyDel (mp);

	keyDel (searchKey);

	kdb_del (kdb);
	keyDel (errorKey);
	ksDel (modules);
}
예제 #2
0
파일: set.c 프로젝트: intfrr/libelektra
/** After writing the key this function rereads the key and print it*/
void check_key()
{
	Key * error_key = keyNew(KEY_END);
	KDB * kdb_handle = kdbOpen(error_key);
	Key * top = keyNew(KEY_END);
	keySetName(top, "user/sw/MyApp"); // == 14
	KeySet * ks = ksNew(0);
	kdbGet(kdb_handle, ks, top);
	Key * key = keyNew(KEY_END);
	keySetName(key, "user/sw/MyApp/Tests/TestKey1"); // == 14
	Key * result = ksLookup(ks, key, KDB_O_NONE);
	const char * key_name = keyName(result);
	const char * key_value = keyString(result);
	const char * key_comment = keyString(keyGetMeta(result, "comment"));
	printf("key: %s value: %s comment: %s", key_name, key_value, key_comment);
	ksDel(ks);
	keyDel(key);
	keyDel(top);
	kdbClose(kdb_handle, error_key);
	keyDel(error_key);
}
예제 #3
0
static void test_umlauts()
{
	printf ("Test umlauts trie\n");

	Trie *trie = test_insert (0, "user/umlauts/test", "slash");
	trie = test_insert (trie, "user/umlauts#test", "hash");
	trie = test_insert (trie, "user/umlauts test", "space");
	trie = test_insert (trie, "user/umlauts\200test", "umlauts");

	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/umlauts/test", KEY_VALUE, "slash", KEY_END);
	keySetName(searchKey, "user/umlauts/test");
	backend = elektraTrieLookup(trie, searchKey);
	succeed_if (backend, "there should be a backend");
	compare_key(backend->mountpoint, mp);


	keySetName(searchKey, "user/umlauts#test");
	keySetName(mp, "user/umlauts#test");
	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/umlauts test");
	keySetName(mp, "user/umlauts test");
	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/umlauts\200test");
	keySetName(mp, "user/umlauts\200test");
	keySetString(mp, "umlauts");
	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);
}
예제 #4
0
/**
 * @internal
 * Create a new key with a different root or common name.
 *
 * Does not modify `key`. The new key needs to be freed after usage.
 *
 * Preconditions: The key name starts with `source`.
 *
 * Example:
 * ```
 * Key * source = keyNew("user/plugins/foo/placements/get", KEY_END);
 * Key * dest = renameKey ("user/plugins/foo", "user/plugins/bar", source);
 * succeed_if_same_string (keyName(dest), "user/plugins/bar/placements/get");
 * ```
 *
 *
 * @param  source Part of the key name to replace
 * @param  dest   Replaces `source`
 * @param  key    key
 * @return        key with new name
 */
static Key * renameKey (const char * source, const char * dest, Key * key)
{
	const char * name = keyName (key);
	char * baseKeyNames = strndup (name + strlen (source), strlen (name));

	Key * moved = keyDup (key);
	keySetName (moved, dest);
	keyAddName (moved, baseKeyNames);

	elektraFree (baseKeyNames);

	return moved;
}
예제 #5
0
파일: ini.c 프로젝트: tryge/libelektra
static void setSectionNumber(Key *parentKey, Key *key, KeySet *ks)
{
	if (!strcmp(keyBaseName(key), INTERNAL_ROOT_SECTION))
	{
		Key *tmpKey = keyDup(key);
		keySetMeta(tmpKey, "ini/section", "0");
		keySetMeta(key, "ini/section", "0");
		keySetString(tmpKey, 0);
		ksAppendKey(ks, tmpKey);
		keyDel(tmpKey);
		return;
	}

	Key *lookupKey = keyDup(key);
	Key *lastKey = keyDup(lookupKey);

	while (1)
	{
		if (!strcmp(keyName(lookupKey), keyName(parentKey)))
		{
			if (keyGetMeta(parentKey, "ini/lastSection"))
			{
				long previousSection = atol(keyString(keyGetMeta(parentKey, "ini/lastSection")));
				++previousSection;
				char buffer[21]; //20 digits (long) + \0
				snprintf(buffer, sizeof (buffer), "%ld", previousSection);
				keySetMeta(parentKey, "ini/lastSection", buffer);
				keySetMeta(key, "ini/section", buffer);
			}
			else
			{
				keySetMeta(parentKey, "ini/lastSection", "1");
				keySetMeta(parentKey, "ini/section", "0");
				keySetMeta(key, "ini/section", "1");
			}
			keySetMeta(lastKey, "ini/section", keyString(keyGetMeta(key, "ini/section")));
			ksAppendKey(ks, lastKey);
			break;
		}
		if (keyGetMeta(ksLookup(ks, lookupKey, KDB_O_NONE), "ini/section"))
		{
			keySetMeta(key, "ini/section", keyString(keyGetMeta(ksLookup(ks, lookupKey, KDB_O_NONE), "ini/section")));
			break;
		}
		keySetName(lastKey, keyName(lookupKey));
		keyAddName(lookupKey, "..");
	}
	keyDel(lookupKey);
	keyDel(lastKey);
}
예제 #6
0
static void test_simple()
{
	printf ("Test simple trie\n");

	Trie *trie = test_insert (0, "user/tests/simple", "simple");

	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/tests/simple", KEY_VALUE, "simple", KEY_END);
	keySetName(searchKey, "user/tests/simple");
	backend = elektraTrieLookup(trie, searchKey);
	succeed_if (backend, "there should be a backend");
	compare_key(backend->mountpoint, mp);


	keySetName(searchKey, "user/tests/simple/below");
	Backend *b2 = elektraTrieLookup(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(trie, searchKey);
	succeed_if (b2, "there should be a backend");
	succeed_if (backend == b2, "should be same backend");
	compare_key(b2->mountpoint, mp);

	elektraTrieClose(trie, 0);
	keyDel (mp);
	keyDel (searchKey);
}
예제 #7
0
파일: kdb.c 프로젝트: KurtMi/libelektra
/**
 * Closes the session with the Key database.
 *
 * @pre The handle must be a valid handle as returned from kdbOpen()
 *
 * @pre errorKey must be a valid key, e.g. created with keyNew()
 *
 * This is the counterpart of kdbOpen().
 *
 * You must call this method when you finished your affairs with the key
 * database. You can manipulate Key and KeySet objects also after
 * kdbClose(), but you must not use any kdb*() call afterwards.
 *
 * The @p handle parameter will be finalized and all resources associated to it
 * will be freed. After a kdbClose(), the @p handle cannot be used anymore.
 *
 * @param handle contains internal information of
 *               @link kdbOpen() opened @endlink key database
 * @param errorKey the key which holds error/warning information
 * @retval 0 on success
 * @retval -1 on NULL pointer
 * @ingroup kdb
 */
int kdbClose (KDB * handle, Key * errorKey)
{
	if (!handle)
	{
		return -1;
	}

	Key * initialParent = keyDup (errorKey);
	int errnosave = errno;
	splitDel (handle->split);

	trieClose (handle->trie, errorKey);

	backendClose (handle->defaultBackend, errorKey);
	handle->defaultBackend = 0;

	// not set in fallback mode, so lets check:
	if (handle->initBackend)
	{
		backendClose (handle->initBackend, errorKey);
		handle->initBackend = 0;
	}

	for (int i = 0; i < NR_GLOBAL_POSITIONS; ++i)
	{
		for (int j = 0; j < NR_GLOBAL_SUBPOSITIONS; ++j)
		{
			elektraPluginClose (handle->globalPlugins[i][j], errorKey);
		}
	}

	if (handle->modules)
	{
		elektraModulesClose (handle->modules, errorKey);
		ksDel (handle->modules);
	}
	else
	{
		ELEKTRA_ADD_WARNING (47, errorKey, "modules were not open");
	}

	elektraFree (handle);

	keySetName (errorKey, keyName (initialParent));
	keySetString (errorKey, keyString (initialParent));
	keyDel (initialParent);
	errno = errnosave;
	return 0;
}
예제 #8
0
파일: lift.c 프로젝트: intfrr/libelektra
int main(int argc, char**argv)
{
	Key *parentKey = keyNew("", KEY_END);
	KDB *kdb = kdbOpen(parentKey);
	KeySet *conf = ksNew(0);

	// get all config files
	kdbGetByName(kdb, conf, parentKey, "/test/lift");
	kdbGetByName(kdb, conf, parentKey, "/test/material_lift");
	kdbGetByName(kdb, conf, parentKey, "/test/heavy_material_lift");
	kdbGetByName(kdb, conf, parentKey, "/test/person_lift");

	// get by params
	int retval = ksGetOpt(argc, argv, conf);
	if (retval & 1)
	{
		printf("%s Version 0.1\n",
			argv[0]);
		return 0;
	}
	else if (retval & 2)
	{
		printf("Usage: %s [OPTIONS]\n"
			"%s\n"
			"Example that demonstrates elektra gen parameters\n",
			argv[0],
			elektraGenHelpText());
		return 0;
	}
	else if (retval != 0)
	{
		printf ("Error in parsing options %d\n", retval);
	}

	// write back to user/test/lift what we got by commandline
	// that means overrides in *_lift are still active, but
	// fallbacks will be overriden.
	if (lift(conf))
	{
		printf("Write out config\n");
		keySetName(parentKey, "user/test/lift");
		kdbSet(kdb, conf, parentKey);
	}

	ksDel(conf);
	kdbClose(kdb, parentKey);
	keyDel(parentKey);
	return retval;
}
예제 #9
0
// keyRel2 helper, returns how many levels check is below key, or 0 if check isn't below
int keyGetLevelsBelow (const Key * key, const Key * check)
{
	if (!keyIsBelow (key, check)) return 0;
	if (keyGetNamespace (key) != keyGetNamespace (check)) return 0;
	Key * toCheck = keyDup (check);
	int levels = 0;
	while (strcmp (keyName (key), keyName (toCheck)))
	{
		keySetBaseName (toCheck, 0);
		if (keyName (toCheck)[0] == '\0') keySetName (toCheck, "/");
		++levels;
	}
	keyDel (toCheck);
	return levels;
}
예제 #10
0
파일: kdb.c 프로젝트: KurtMi/libelektra
/**
 * @internal
 *
 * @brief Check if an update is needed at all
 *
 * @retval -1 an error occurred
 * @retval 0 no update needed
 * @retval number of plugins which need update
 */
static int elektraGetCheckUpdateNeeded (Split * split, Key * parentKey)
{
	int updateNeededOccurred = 0;
	for (size_t i = 0; i < split->size; i++)
	{
		int ret = -1;
		Backend * backend = split->handles[i];
		clear_bit (split->syncbits[i], 1);

		if (backend->getplugins[RESOLVER_PLUGIN] && backend->getplugins[RESOLVER_PLUGIN]->kdbGet)
		{
			ksRewind (split->keysets[i]);
			keySetName (parentKey, keyName (split->parents[i]));
			keySetString (parentKey, "");
			ret = backend->getplugins[RESOLVER_PLUGIN]->kdbGet (backend->getplugins[RESOLVER_PLUGIN], split->keysets[i],
									    parentKey);
			// store resolved filename
			keySetString (split->parents[i], keyString (parentKey));
			// no keys in that backend
			backendUpdateSize (backend, split->parents[i], 0);
		}
		// TODO: set error in else case!

		switch (ret)
		{
		case 1:
			// Seems like we need to sync that
			set_bit (split->syncbits[i], SPLIT_FLAG_SYNC);
			++updateNeededOccurred;
			break;
		case 0:
			// Nothing to do here
			break;
		default:
			ELEKTRA_ASSERT (0, "resolver did not return 1 0 -1, but %d", ret);
		case -1:
			// Ohh, an error occurred, lets stop the
			// process.
			return -1;
		}
	}
	return updateNeededOccurred;
}
예제 #11
0
void test_tempname()
{
	printf ("Resolve Tempname\n");

	KeySet *modules = ksNew(0);
	elektraModulesInit (modules, 0);

	Plugin *plugin = elektraPluginOpen("resolver", modules, set_pluginconf(), 0);
	exit_if_fail (plugin, "could not load resolver plugin");

	KeySet *test_config = set_pluginconf();
	KeySet *config = elektraPluginGetConfig (plugin);
	succeed_if (config != 0, "there should be a config");
	compare_keyset(config, test_config);
	ksDel (test_config);

	succeed_if (plugin->kdbOpen != 0, "no open pointer");
	succeed_if (plugin->kdbClose != 0, "no open pointer");
	succeed_if (plugin->kdbGet != 0, "no open pointer");
	succeed_if (plugin->kdbSet != 0, "no open pointer");
	succeed_if (plugin->kdbError!= 0, "no open pointer");

	succeed_if (!strcmp(plugin->name, "resolver"), "got wrong name");

	resolverHandles *h = elektraPluginGetData(plugin);
	succeed_if (h != 0, "no plugin handle");

	Key *parentKey= keyNew("system", KEY_END);
	plugin->kdbGet(plugin, 0, parentKey);
	succeed_if (!strncmp(h->system.tempfile, KDB_DB_SYSTEM "/elektra.ecf", sizeof(KDB_DB_SYSTEM)),
			"resulting filename not correct");

	keySetName(parentKey, "user");
	plugin->kdbGet(plugin, 0, parentKey);
	succeed_if (!strncmp(h->user.tempfile, KDB_DB_HOME "/" KDB_DB_USER "/elektra.ecf.tmp", sizeof(KDB_DB_HOME "/" KDB_DB_USER)),
			"resulting filename not correct");

	keyDel (parentKey);
	elektraPluginClose(plugin, 0);
	elektraModulesClose(modules, 0);
	ksDel (modules);
}
예제 #12
0
int main ()
{
	key = keyNew (KEY_ROOT, KEY_END);

	timeInit ();
	benchmarkCreate ();
	timePrint ("Created empty keyset");

	benchmarkFillup ();
	timePrint ("New large keyset");

	benchmarkOpen ();
	keySetName (key, KEY_ROOT);
	timePrint ("Opened key database");

	benchmarkInread ();
	timePrint ("Initialize read");

	benchmarkInwrite ();
	timePrint ("Initialize write");

	benchmarkWriteout ();
	timePrint ("Write key database");

	benchmarkRewrite ();
	timePrint ("Rewrite key database");

	benchmarkReadin ();
	timePrint ("Read in key database");

	benchmarkLookupByName ();
	timePrint ("Lookup key database");

	benchmarkReread ();
	timePrint ("Re read key database");

	benchmarkClose ();
	timePrint ("Closed key database");

	ksDel (large);
	keyDel (key);
}
예제 #13
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);
}
예제 #14
0
파일: augeas.c 프로젝트: beku/libelektra
static Key *createKeyFromPath(Key *parentKey, const char *treePath)
{
	Key *key = keyDup (parentKey);
	const char *baseName = (treePath + strlen (AUGEAS_TREE_ROOT) + 1);

	size_t baseSize = keyGetNameSize(key);
	size_t keyNameSize = strlen (baseName) + baseSize + 1;
	char *newName = malloc (keyNameSize);

	if (!newName) return 0;

	strcpy (newName, keyName (key));
	newName[baseSize - 1] = KDB_PATH_SEPARATOR;
	newName[baseSize] = 0;
	strcat (newName, baseName);

	keySetName(key, newName);
	free (newName);

	return key;
}
예제 #15
0
int main()
{
	KeySet *myConfig = ksNew(0, KS_END);
	Key *key = keyNew("system/test/myapp",KEY_END);
	KDB *handle = kdbOpen(key);

	kdbGet(handle, myConfig, key);

	keySetName(key, "user/test/myapp");
	kdbGet(handle, myConfig, key);

	// check for errors in key
	keyDel(key);

	/*
	ksRewind(myConfig);
	while ((key = ksNext(myConfig)))
	{
		printf ("%s\n", keyName(key));
	}
	*/

	key = ksLookupByName(myConfig,"/test/myapp/key", 0);

	// check if key is not 0 and work with it...
	if (key)
	{
		printf("%s\n", keyString(key));
	}

	ksDel (myConfig); // delete the in-memory configuration


	// maybe you want kdbSet() myConfig here

	kdbClose(handle, 0); // no more affairs with the key database.
	return 0;
}
예제 #16
0
파일: kdb.c 프로젝트: KurtMi/libelektra
/**
 * @internal
 * @brief Does the rollback
 *
 * @param split all information for iteration
 * @param parentKey to add warnings (also passed to plugins for the same reason)
 */
static void elektraSetRollback (Split * split, Key * parentKey)
{
	for (size_t p = 0; p < NR_OF_PLUGINS; ++p)
	{
		for (size_t i = 0; i < split->size; i++)
		{
			int ret = 0;
			Backend * backend = split->handles[i];

			ksRewind (split->keysets[i]);
			if (backend->errorplugins[p])
			{
				keySetName (parentKey, keyName (split->parents[i]));
				ret = backend->errorplugins[p]->kdbError (backend->errorplugins[p], split->keysets[i], parentKey);
			}

			if (ret == -1)
			{
				ELEKTRA_ADD_WARNING (81, parentKey, keyName (backend->mountpoint));
			}
		}
	}
}
예제 #17
0
파일: kdb.c 프로젝트: KurtMi/libelektra
/**
 * @internal
 * @brief Does the commit
 *
 * @param split all information for iteration
 * @param parentKey to add warnings (also passed to plugins for the same reason)
 */
static void elektraSetCommit (Split * split, Key * parentKey)
{
	for (size_t p = COMMIT_PLUGIN; p < NR_OF_PLUGINS; ++p)
	{
		for (size_t i = 0; i < split->size; i++)
		{
			int ret = 0;
			Backend * backend = split->handles[i];

			if (backend->setplugins[p] && backend->setplugins[p]->kdbSet)
			{
				if (p != COMMIT_PLUGIN)
				{
					keySetString (parentKey, keyString (split->parents[i]));
				}
				keySetName (parentKey, keyName (split->parents[i]));
#if DEBUG && VERBOSE
				printf ("elektraSetCommit: %p # %zu with %s - %s\n", backend, p, keyName (parentKey),
					keyString (parentKey));
#endif
				ksRewind (split->keysets[i]);
				ret = backend->setplugins[p]->kdbSet (backend->setplugins[p], split->keysets[i], parentKey);
				if (p == COMMIT_PLUGIN)
				{
					// name of non-temp file
					keySetString (split->parents[i], keyString (parentKey));
				}
			}

			if (ret == -1)
			{
				ELEKTRA_ADD_WARNING (80, parentKey, keyName (backend->mountpoint));
			}
		}
	}
}
static void test_cascading()
{
	printf ("Test simple mount with cascading\n");

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

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

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

	succeed_if (kdb->split->size == 7, "size of split not correct");
	Key *mp = keyNew("dir/tests/simple", KEY_VALUE, "simple", KEY_END);
	compare_key(mp, kdb->split->parents[0]);
	keySetName(mp, "user/tests/simple"); keySetString (mp, "simple");
	compare_key(mp, kdb->split->parents[1]);
	keySetName(mp, "system/tests/simple"); keySetString (mp, "simple");
	compare_key(mp, kdb->split->parents[2]);
	keyDel (mp);

	// output_split (kdb->split);
	// output_trie (kdb->trie);

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

	keySetName(searchKey, "system");
	backend = elektraTrieLookup(kdb->trie, searchKey);
	succeed_if (!backend, "there should be no backend");


	mp = keyNew("", KEY_VALUE, "simple", KEY_END);
	elektraKeySetName(mp, "/tests/simple", KEY_CASCADING_NAME);

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


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

	keySetName(searchKey, "system/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, "system/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);


	keyDel (errorKey);
	ksDel (modules);
	keyDel (mp);
	keyDel (searchKey);
	kdb_del (kdb);
}
예제 #19
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);

	}
}
예제 #20
0
static void test_revmoreiterate()
{
	printf ("Test revmoreiterate trie\n");

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

	Trie *trie = 0;
	switch (i)
	{
	case 0:
		trie = test_insert (trie, "user/tests", "tests");
		trie = test_insert (trie, "user/tests/hosts", "hosts");
		trie = test_insert (trie, "user/tests/hosts/below", "below");
		trie = test_insert (trie, "system/tests", "systests");
		trie = test_insert (trie, "system/tests/hosts", "syshosts");
		trie = test_insert (trie, "system/tests/hosts/below", "sysbelow");
		trie = test_insert (trie, "system", "system");
		trie = test_insert (trie, "user", "user");
		break;
	case 1:
		trie = test_insert (trie, "system/tests/hosts", "syshosts");
		trie = test_insert (trie, "system", "system");
		trie = test_insert (trie, "user/tests", "tests");
		trie = test_insert (trie, "user/tests/hosts", "hosts");
		trie = test_insert (trie, "user/tests/hosts/below", "below");
		trie = test_insert (trie, "system/tests", "systests");
		trie = test_insert (trie, "user", "user");
		trie = test_insert (trie, "system/tests/hosts/below", "sysbelow");
		break;
	case 2:
		trie = test_insert (trie, "system/tests/hosts/below", "sysbelow");
		trie = test_insert (trie, "system/tests/hosts", "syshosts");
		trie = test_insert (trie, "user/tests/hosts/below", "below");
		trie = test_insert (trie, "user/tests/hosts", "hosts");
		trie = test_insert (trie, "user/tests", "tests");
		trie = test_insert (trie, "user", "user");
		trie = test_insert (trie, "system/tests", "systests");
		trie = test_insert (trie, "system", "system");
		break;
	case 3:
		trie = test_insert (trie, "user/tests/hosts/below", "below");
		trie = test_insert (trie, "user/tests/hosts", "hosts");
		trie = test_insert (trie, "user/tests", "tests");
		trie = test_insert (trie, "user", "user");
		trie = test_insert (trie, "system/tests/hosts/below", "sysbelow");
		trie = test_insert (trie, "system/tests/hosts", "syshosts");
		trie = test_insert (trie, "system/tests", "systests");
		trie = test_insert (trie, "system", "system");
		break;
	case 4:
		trie = test_insert (trie, "system/tests/hosts/below", "sysbelow");
		trie = test_insert (trie, "system/tests/hosts", "syshosts");
		trie = test_insert (trie, "system/tests", "systests");
		trie = test_insert (trie, "system", "system");
		trie = test_insert (trie, "user/tests/hosts/below", "below");
		trie = test_insert (trie, "user/tests/hosts", "hosts");
		trie = test_insert (trie, "user/tests", "tests");
		trie = test_insert (trie, "user", "user");
		break;
	}

	KeySet *mps = set_mountpoints();

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

	Key *searchKey = keyNew(0);

	keySetName(searchKey, "user");
	Backend *backend = elektraTrieLookup(trie, searchKey);
	succeed_if (backend, "there should be a backend");
	compare_key(backend->mountpoint, ksLookupByName(mps, "user",0));
	// printf ("backend: %p\n", (void*)backend);


	keySetName(searchKey, "user/tests/hosts/other/below");
	Backend *b2 = elektraTrieLookup(trie, searchKey);
	succeed_if (b2, "there should be a backend");
	compare_key(b2->mountpoint, ksLookupByName(mps, "user/tests/hosts",0));
	// printf ("b2: %p\n", (void*)b2);


	keySetName(searchKey, "user/tests/hosts/other/deep/below");
	b2 = elektraTrieLookup(trie, searchKey);
	succeed_if (b2, "there should be a backend");
	compare_key(b2->mountpoint, ksLookupByName(mps, "user/tests/hosts",0));


	keySetName(searchKey, "user/tests/hosts/below");
	Backend *b3 = elektraTrieLookup(trie, searchKey);
	succeed_if (b3, "there should be a backend");
	compare_key(b3->mountpoint, ksLookupByName(mps, "user/tests/hosts/below",0));
	backend = b3;
	// printf ("b3: %p\n", (void*)b3);


	keySetName(searchKey, "user/tests/hosts/below/other/deep/below");
	b2 = elektraTrieLookup(trie, searchKey);
	succeed_if (b3, "there should be a backend");
	compare_key(b3->mountpoint, ksLookupByName(mps, "user/tests/hosts/below",0));

	keySetName(searchKey, "system");
	backend = elektraTrieLookup(trie, searchKey);
	succeed_if (backend, "there should be a backend");
	compare_key(backend->mountpoint, ksLookupByName(mps, "system",0));
	// printf ("backend: %p\n", (void*)backend);


	keySetName(searchKey, "system/tests/hosts/other/below");
	b2 = elektraTrieLookup(trie, searchKey);
	succeed_if (b2, "there should be a backend");
	compare_key(b2->mountpoint, ksLookupByName(mps, "system/tests/hosts",0));
	// printf ("b2: %p\n", (void*)b2);


	keySetName(searchKey, "system/tests/hosts/other/deep/below");
	b2 = elektraTrieLookup(trie, searchKey);
	succeed_if (b2, "there should be a backend");
	compare_key(b2->mountpoint, ksLookupByName(mps, "system/tests/hosts",0));


	keySetName(searchKey, "system/tests/hosts/below");
	b3 = elektraTrieLookup(trie, searchKey);
	succeed_if (b3, "there should be a backend");
	compare_key(b3->mountpoint, ksLookupByName(mps, "system/tests/hosts/below",0));
	backend = b3;
	// printf ("b3: %p\n", (void*)b3);


	keySetName(searchKey, "system/tests/hosts/below/other/deep/below");
	b2 = elektraTrieLookup(trie, searchKey);
	succeed_if (b3, "there should be a backend");
	compare_key(b3->mountpoint, ksLookupByName(mps, "system/tests/hosts/below",0));

	/*
	printf ("---------\n");
	output_trie(trie);
	*/

	KeySet *mps_cmp = ksNew(0, KS_END);
	collect_mountpoints(trie, mps_cmp);
	succeed_if (ksGetSize(mps_cmp) == 8, "size should be 8");
	compare_keyset(mps, mps_cmp);

	ksDel (mps_cmp);
	ksDel (mps);

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

	} // end for
}
예제 #21
0
static void test_reviterate()
{
	printf ("Test reviterate trie\n");

	Trie * trie = test_insert (0, "user/tests/hosts/below", "below");
	trie = test_insert (trie, "user/tests/hosts", "hosts");

	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/tests/hosts", KEY_VALUE, "hosts", KEY_END);
	keySetName(searchKey, "user/tests/hosts");
	backend = elektraTrieLookup(trie, searchKey);
	succeed_if (backend, "there should be a backend");
	compare_key(backend->mountpoint, mp);
	// printf ("backend: %p\n", (void*)backend);


	keySetName(searchKey, "user/tests/hosts/other/below");
	Backend *b2 = elektraTrieLookup(trie, searchKey);
	succeed_if (b2, "there should be a backend");
	succeed_if (backend == b2, "should be same backend");
	compare_key(b2->mountpoint, mp);
	// printf ("b2: %p\n", (void*)b2);


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


	Key *mp2 = keyNew("user/tests/hosts/below", KEY_VALUE, "below", KEY_END);
	keySetName(searchKey, "user/tests/hosts/below");
	Backend *b3 = elektraTrieLookup(trie, searchKey);
	succeed_if (b3, "there should be a backend");
	succeed_if (backend != b3, "should be different backend");
	compare_key(b3->mountpoint, mp2);
	backend = b3;
	// printf ("b3: %p\n", (void*)b3);


	keySetName(searchKey, "user/tests/hosts/below/other/deep/below");
	b2 = elektraTrieLookup(trie, searchKey);
	succeed_if (b3, "there should be a backend");
	succeed_if (backend == b3, "should be same backend");
	compare_key(b3->mountpoint, mp2);

	KeySet *mps = ksNew(0, KS_END);
	collect_mountpoints(trie, mps);
	succeed_if (ksGetSize (mps) == 2, "not both mountpoints collected");
	compare_key(ksHead(mps), mp);
	compare_key(ksTail(mps), mp2);
	ksDel (mps);

	elektraTrieClose(trie, 0);

	keyDel (mp);
	keyDel (mp2);
	keyDel (searchKey);
}
예제 #22
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
}
예제 #23
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);
}
예제 #24
0
파일: kdbtools.c 프로젝트: tryge/libelektra
/*
 * Processes the current <key> node from reader, converting from XML
 * to a Key object, and ksAppendKey() it to ks.
 *
 * See keyToStream() for an example of a <key> node.
 *
 * This function is completelly dependent on libxml.
 * 
 * @param ks where to put the resulting reded key
 * @param context a prent key name, so a full name can be calculated
 *        if the XML node for the current key only provides a basename
 * @param reader where to read from
 */
static int consumeKeyNode(KeySet *ks, const char *context, xmlTextReaderPtr reader)
{
	xmlChar *nodeName=0;
	xmlChar *keyNodeName=0;
	xmlChar *buffer=0;
	xmlChar *privateContext=0;
	Key *newKey=0;
	int appended=0;

	/* printf("%s", KDB_SCHEMA_PATH); */
	
	keyNodeName=xmlTextReaderName(reader);
	if (!strcmp((char *)keyNodeName,"key")) {
		mode_t isdir=0;
		int isbin=0;
		int end=0;
		
		newKey=keyNew(0);

		/* a <key> must have one of the following:
		   - a "name" attribute, used as an absolute name overriding the context
		   - a "basename" attribute, that will be appended to the current context
		   - a "parent" plus "basename" attributes, both appended to current context
		   - only a "parent", appended to current context
		*/
		buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"name");
		if (buffer) {
			/* set absolute name */
			keySetName(newKey,(char *)buffer);
			xmlFree(buffer); buffer=0;
		} else {
			/* logic for relative name calculation */
			
			privateContext=xmlTextReaderGetAttribute(reader,
				(const xmlChar *)"parent");
			buffer=xmlTextReaderGetAttribute(reader,
				(const xmlChar *)"basename");

			if (context) keySetName(newKey,context);
			if (privateContext) keyAddName(newKey, (char *)privateContext);
			if (buffer) keyAddName(newKey,(char *)buffer);

			xmlFree(privateContext); privateContext=0;
			xmlFree(buffer); buffer=0;
		}


		/* test for a short value attribute, instead of <value> bellow */
		buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"value");
		if (buffer) {
			keySetRaw(newKey,buffer,elektraStrLen((char *)buffer));
			xmlFree(buffer); buffer=0;
		}

		/* Parse UID */
		buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"uid");
		if (buffer) {
			int errsave = errno;
			char * endptr;
			long int uid = strtol ((const char *)buffer, &endptr, 10);
			errno = errsave;
			if (endptr != '\0' && *endptr == '\0')
			{
				keySetUID(newKey,uid);
			}
			xmlFree(buffer); buffer=0;
		}

		/* Parse GID */
		buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"gid");
		if (buffer) {
			int errsave = errno;
			char * endptr;
			long int gid = strtol ((const char *)buffer, &endptr, 10);
			errno = errsave;
			if (endptr != '\0' && *endptr == '\0')
			{
				keySetGID(newKey,gid);
			}
			xmlFree(buffer); buffer=0;
		}

		/* Parse mode permissions */
		buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"mode");
		int errsave = errno;
		if (buffer) keySetMode(newKey,strtol((char *)buffer,0,0));
		errno = errsave;
		xmlFree(buffer);



		if (xmlTextReaderIsEmptyElement(reader)) {
			/* we have a <key ..../> element */
			if (newKey && !appended) {
				ksAppendKey(ks,newKey);
				appended=1;
				end=1;
			}
		}

		buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"type");
		if (buffer)
		{
			if (!strcmp((char *)buffer,"binary")) isbin = 1;
			else if (!strcmp((char *)buffer,"bin")) isbin = 1;
		}
		xmlFree(buffer);

		/* If "isdir" appears, everything different from "0", "false" or "no"
		marks it as a dir key */
		buffer=xmlTextReaderGetAttribute(reader,(const xmlChar *)"isdir");
		if (!isdir && buffer)
		{
			if (	strcmp((char *)buffer,"0") &&
				strcmp((char *)buffer,"false") &&
				strcmp((char *)buffer,"no"))
				isdir = 1;
			else	isdir = 0;
		}
		xmlFree(buffer);

		if (isdir) keySetDir(newKey);
		if (isbin) keySetMeta (newKey, "binary", "");

		// TODO: should parse arbitrary attributes as metadata

		/* Parse everything else */
		while (!end) {
			xmlTextReaderRead(reader);
			nodeName=xmlTextReaderName(reader);

			if (!strcmp((char *)nodeName,"value")) {
				if (xmlTextReaderIsEmptyElement(reader) ||
					xmlTextReaderNodeType(reader)==15)
				{
					xmlFree (nodeName);
					continue;
				}
					
				xmlTextReaderRead(reader);
				buffer=xmlTextReaderValue(reader);
				
				if (buffer) {
					/* Key's value type was already set above */
					if (keyIsBinary(newKey)) {
						/* TODO binary values
						char *unencoded=0;
						size_t unencodedSize;
						
						unencodedSize=elektraStrLen((char *)buffer)/2;
						unencoded=elektraMalloc(unencodedSize);
						unencodedSize=kdbbDecode((char *)buffer,unencoded);
						if (!unencodedSize) return -1;
							keySetRaw(newKey,unencoded,unencodedSize);
						elektraFree (unencoded);
						*/
					} else keySetRaw(newKey,buffer,elektraStrLen((char *)buffer));
				}
				xmlFree(buffer);
			} else if (!strcmp((char *)nodeName,"comment")) {
				ssize_t commentSize=0;
				
				if (xmlTextReaderIsEmptyElement(reader) ||
					xmlTextReaderNodeType(reader)==15)
				{
					xmlFree (nodeName);
					continue;
				}
					
				xmlTextReaderRead(reader);
				buffer=xmlTextReaderValue(reader);
				
				if ((commentSize=keyGetCommentSize(newKey)) > 1) {
					/*Multiple line comment*/
					char *tmpComment=0;
					tmpComment=elektraMalloc(commentSize+
						xmlStrlen(buffer)*sizeof(xmlChar)+1);

					if (tmpComment) {
						keyGetComment(newKey,tmpComment,commentSize);

						strcat(tmpComment,"\n");
						strcat(tmpComment,(char *)buffer);

						keySetComment(newKey,tmpComment);

						elektraFree (tmpComment); tmpComment=0;
					}
				} else keySetComment(newKey,(char *)buffer);
				xmlFree(buffer);
			} else if (!strcmp((char *)nodeName,"key")) {
				/* Here we found </key> or a sub <key>.
				   So include current key in the KeySet. */
				if (newKey && !appended) {
					ksAppendKey(ks,newKey);
					appended=1;
				}
				
				if (xmlTextReaderNodeType(reader)==15)
					/* found a </key> */
					end=1;
				else {
					/* found a sub <key> */
					/* prepare the context (parent) */
					consumeKeyNode(ks,newKey->key,reader);
				}
			}

			xmlFree (nodeName);
		}

		if (privateContext) xmlFree(privateContext);

		/* seems like we forgot the key, lets delete it */
		if (newKey && !appended) {
			keyDel (newKey);
			appended=1;
		}
	}

	xmlFree(keyNodeName);
	
	return 0;
}
예제 #25
0
int main() {
	KeySet *ks=ksNew(0);
	Key *key=0;

	printf ("Generate some keys...");

	ksAppendKey(ks,keyNew("user/sw",KEY_END));  /* a simple key */

	ksAppendKey(ks,keyNew(0));     /* an empty key */

	ksAppendKey(ks,keyNew("system/sw",
		KEY_END));

	ksAppendKey(ks,keyNew("user/tmp/ex1",
		KEY_VALUE,"some data",        /* with a simple value */
		KEY_END));                    /* end of args */

	ksAppendKey(ks,keyNew("user/tmp/ex2",
		KEY_VALUE,"some data",        /* with a simple value */
		KEY_MODE,0777,                /* permissions */
		KEY_END));                    /* end of args */

	ksAppendKey(ks,keyNew("user/tmp/ex4",
		KEY_BINARY,
		KEY_COMMENT,"value is truncated",
		KEY_SIZE, 7,
		KEY_VALUE,"some data",        /* value that will be truncated to 7 bytes */
		KEY_UID,0,                    /* root uid */
		KEY_END));                    /* end of args */

	ksAppendKey(ks,keyNew("user/tmp/ex5",
		KEY_VALUE,"some data",        /* value  */
		KEY_OWNER,"root",            /* owner (not uid) is root */
		KEY_COMMENT,"some comment",   /* a comment */
		KEY_END));                    /* end of args */

	ksAppendKey(ks,keyNew("user/env/alias/ls",  /* a key we know we have */
		KEY_END));                    /* do nothing more */

	ksAppendKey(ks,keyNew("user/env/alias/ls",  /* same key, to compare in output */
		KEY_OWNER,"root",            /* set new owner (not uid) as root */
		KEY_COMMENT,"new comment",    /* set new comment */
		KEY_END));                    /* end of args */

	key=keyNew("user/test//", KEY_END);

	/* we are providing a lot of '/' to see it being removed */
	keySetName(key,"system");
	keySetName(key,"user");
	keySetName(key,"user:aviram");
	keySetName(key,"user///abc//////def///");
	keySetName(key,"user:root///aaa//////bbb///");

	keyAddBaseName(key,"tmp");
	keyAddBaseName(key,"////ex6///exx7///");
	keySetBaseName(key,"ex8");
	keySetBaseName(key,"ex9");
	keyAddBaseName(key,"///exxx9///ex10///ex\\/11///");
	keySetBaseName(key,"ex12");
	keySetBaseName(key,"ex13///");
	ksAppendKey(ks,key);

	ksDel(ks);

	printf ("finished\n");

	return 0;
}
예제 #26
0
int keyRel2 (const Key * key, const Key * check, KeyRelType which)
{
	if (!key || !check) return -1;
	if (!key->key || !check->key) return -1;

	Key * cKey = keyAsCascading (key);
	Key * cCheck = keyAsCascading (check);
	Key * cKeyParent = keyDup (cKey);
	keySetBaseName (cKeyParent, 0);
	if (keyName (cKeyParent)[0] == '\0') keySetName (cKeyParent, "/");
	int isBelow = 0;
	int isSilblingNephew = 0;
	isBelow = keyGetLevelsBelow (cKey, cCheck);
	if (!isBelow) isSilblingNephew = keyGetLevelsBelow (cKeyParent, cCheck);
	elektraNamespace keyNamespace = keyGetNamespace (key);
	elektraNamespace checkNamespace = keyGetNamespace (check);
	int retVal = 0;
	int bits = 0;
	for (KeyRelType type = 1; type != 0; type <<= 1)
	{
		if (type & which) ++bits;
	}
	if (bits != 1) return -1;
	switch (which)
	{
	case ELEKTRA_REL_BELOW_SAME_NS:
		if (isBelow && (keyNamespace == checkNamespace)) retVal = isBelow;
		break;
	case ELEKTRA_REL_BELOW_IGNORE_NS:
		if (isBelow) retVal = isBelow;
		break;
	case ELEKTRA_REL_BELOW_CASCADING_NS:
		if (isBelow && ((checkNamespace == KEY_NS_CASCADING) || (keyNamespace == KEY_NS_CASCADING))) retVal = isBelow;
		break;
	case ELEKTRA_REL_DIRECT_BELOW_SAME_NS:
		if ((isBelow == 1) && (keyNamespace == checkNamespace)) retVal = 1;
		break;
	case ELEKTRA_REL_DIRECT_BELOW_IGNORE_NS:
		if (isBelow == 1) retVal = 1;
		break;
	case ELEKTRA_REL_DIRECT_BELOW_CASCADING_NS:
		if ((isBelow == 1) && ((checkNamespace == KEY_NS_CASCADING) || (keyNamespace == KEY_NS_CASCADING))) retVal = 1;
		break;
	case ELEKTRA_REL_SILBLING_SAME_NS:
		if ((isSilblingNephew == 1) && (keyNamespace == checkNamespace)) retVal = 1;
		break;
	case ELEKTRA_REL_SILBLING_IGNORE_NS:
		if (isSilblingNephew == 1) retVal = 1;
		break;
	case ELEKTRA_REL_SILBLING_CASCADING_NS:
		if ((isSilblingNephew == 1) && ((checkNamespace == KEY_NS_CASCADING) || (keyNamespace == KEY_NS_CASCADING))) retVal = 1;
		break;
	case ELEKTRA_REL_NEPHEW_SAME_NS:
		if ((isSilblingNephew > 1) && (keyNamespace == checkNamespace)) retVal = isSilblingNephew - 1;
		break;
	case ELEKTRA_REL_NEPHEW_IGNORE_NS:
		if (isSilblingNephew > 1) retVal = isSilblingNephew - 1;
		break;
	case ELEKTRA_REL_NEPHEW_CASCADING_NS:
		if ((isSilblingNephew > 1) && ((checkNamespace == KEY_NS_CASCADING) || (keyNamespace == KEY_NS_CASCADING)))
			retVal = isSilblingNephew - 1;
		break;
	default:
		retVal = -1;
		break;
	}
	keyDel (cKey);
	keyDel (cCheck);
	keyDel (cKeyParent);
	return retVal;
}
예제 #27
0
static void test_search()
{
	printf ("Testing operation search (internal)\n");

	KeySet *a = set_a();
	Key *s = keyNew("user/a", KEY_END);
	ssize_t result;

	keySetName (s, "user/0");
	result = ksSearchInternal (a, s);
	succeed_if (result == 0, "insertpos wrong");

	keySetName (s, "user/a");
	result = ksSearchInternal (a, s);
	succeed_if (result == 1, "insertpos wrong");

	keySetName (s, "user/a/0");
	result = ksSearchInternal (a, s);
	succeed_if (result == -3, "insertpos wrong");

	keySetName (s, "user/a/a");
	result = ksSearchInternal (a, s);
	succeed_if (result == 2, "insertpos wrong");

	keySetName (s, "user/a/a/a");
	result = ksSearchInternal (a, s);
	succeed_if (result == 3, "insertpos wrong");

	keySetName (s, "user/a/a/b");
	result = ksSearchInternal (a, s);
	succeed_if (result == 4, "insertpos wrong");

	keySetName (s, "user/a/b");
	result = ksSearchInternal (a, s);
	succeed_if (result == 5, "insertpos wrong");

	keySetName (s, "user/a/b/a");
	result = ksSearchInternal (a, s);
	succeed_if (result == 6, "insertpos wrong");

	keySetName (s, "user/a/b/b");
	result = ksSearchInternal (a, s);
	succeed_if (result == 7, "insertpos wrong");

	keySetName (s, "user/a/c");
	result = ksSearchInternal (a, s);
	succeed_if (result == 8, "insertpos wrong");

	keySetName (s, "user/a/d");
	result = ksSearchInternal (a, s);
	succeed_if (result == 9, "insertpos wrong");

	keySetName (s, "user/a/x");
	result = ksSearchInternal (a, s);
	succeed_if (result == -11, "insertpos wrong");

	keySetName (s, "user/a/x/a");
	result = ksSearchInternal (a, s);
	succeed_if (result == 10, "insertpos wrong");

	keySetName (s, "user/a/x/b");
	result = ksSearchInternal (a, s);
	succeed_if (result == 11, "insertpos wrong");

	keySetName (s, "user/a/x/c");
	result = ksSearchInternal (a, s);
	succeed_if (result == 12, "insertpos wrong");

	keySetName (s, "user/a/x/c/a");
	result = ksSearchInternal (a, s);
	succeed_if (result == 13, "insertpos wrong");

	keySetName (s, "user/a/x/c/b");
	result = ksSearchInternal (a, s);
	succeed_if (result == 14, "insertpos wrong");

	keySetName (s, "user/x");
	result = ksSearchInternal (a, s);
	succeed_if (result == 15, "insertpos wrong");

	/*
	   Generation of new Testcases:
	for (int i=0; i< 16; ++i)
	{
		s = a->array[i];
		printf ("keySetName (s, \"%s\");\n", keyName(s));
		printf ("result = ksSearchInternal (a, s);\n");
		printf ("succeed_if (result == %zd, \"insertpos wrong\");\n\n", ksSearchInternal (a, s));
	}
	*/

	keyDel (s);
	ksDel (a);
}
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
NSS_STATUS _nss_registry_getspnam_r (const char *name, struct spwd * pw,
                                     char *buffer, size_t buflen, int *errnop)
{
    int i;
    char *tmpbuf=NULL;
    Key *tmpkey;

    *errnop = ENOENT;

    /* Open registry connection */
    registryOpen();
    if(_nss_registry_finduserbyname(name) == NSS_STATUS_NOTFOUND) return NSS_STATUS_NOTFOUND;
    /* Yay! the users exists, lets continue */
    pw->sp_namp = (char *)_nss_registry_copy_to_buffer(&buffer,&buflen,name);
    if(! pw->sp_namp)
        goto out_nomem;

    tmpbuf = _nss_registry_get_string(REGISTRYUSER, pw->sp_namp,"shadowPassword");
    if(!_nss_registry_isempty(tmpbuf))
    {
        pw->sp_pwdp =  (char *)_nss_registry_copy_to_buffer(&buffer,&buflen,tmpbuf);
        free(tmpbuf);
    } else
    {
        /* If password is empty, set it to an empty string..If it's still empty, fail */
        pw->sp_pwdp =  (char *)_nss_registry_copy_to_buffer(&buffer,&buflen,"");
    }

    if(!pw->sp_pwdp)
        goto out_nomem;
    /*tmpbuf = _nss_registry_get_string(REGISTRYUSER, pw->sp_namp,"passwdLastChange");*/
    /* It's expected to be returned in this format
     * OK. It's a long and evil way to do this, but I don't have much choice.
     * returns last time password was changed, whether it was comment or
     * actual password */
    tmpbuf = (char *)malloc(255);
    sprintf(tmpbuf, "system/users/%s/shadowPassword",pw->sp_namp);
    tmpkey = (Key *)malloc(sizeof(Key));
    keyInit(tmpkey);
    keySetName(tmpkey, tmpbuf);
    registryStatKey(tmpkey);
    pw->sp_lstchg = keyGetMTime(tmpkey) / (60 * 60 * 24);
    keyClose(tmpkey);
    free(tmpkey);
    free(tmpbuf);

    tmpbuf = _nss_registry_get_string(REGISTRYUSER, pw->sp_namp,"passwdChangeBefore");
    pw->sp_min = _nss_registry_strtol(tmpbuf,FALLBACK,&i);
    if (i)
    {
        _nss_registry_log(LOG_ERR,"User %s has invalid passwdChangeBefore (%s). "
                          " Reverted to %d. Fix you registry entries.",
                          pw->sp_namp, tmpbuf||"NULL",
                          pw->sp_min);
    }
    if (tmpbuf != NULL)
        free(tmpbuf);

    tmpbuf = _nss_registry_get_string(REGISTRYUSER, pw->sp_namp,"passwdChangeAfter");
    pw->sp_max = _nss_registry_strtol(tmpbuf,FALLBACK,&i);
    if (i)
    {
        _nss_registry_log(LOG_ERR,"User %s has invalid passwdChangeAfter (%s). "
                          " Reverted to %d. Fix you registry entries.",
                          pw->sp_namp, tmpbuf||"NULL",
                          pw->sp_max);
    }
    if (tmpbuf != NULL)
        free(tmpbuf);

    tmpbuf = _nss_registry_get_string(REGISTRYUSER, pw->sp_namp,"passwdWarnBefore");
    pw->sp_warn = _nss_registry_strtol(tmpbuf,FALLBACK,&i);
    if (i)
    {
        _nss_registry_log(LOG_ERR,"User %s has invalid passwdWarnBefore (%s). "
                          " Reverted to %d. Fix you registry entries.",
                          pw->sp_namp, tmpbuf||"NULL",
                          pw->sp_warn);
    }
    if (tmpbuf != NULL)
        free(tmpbuf);

    tmpbuf = _nss_registry_get_string(REGISTRYUSER, pw->sp_namp,"passwdDisableAfter");
    pw->sp_inact = _nss_registry_strtol(tmpbuf,FALLBACK,&i);
    /* Don't warn in this case since it seems quite normal to not have that set..
     * At least on my system */
    if(tmpbuf != NULL)
        free(tmpbuf);

    tmpbuf = _nss_registry_get_string(REGISTRYUSER, pw->sp_namp,"passwdDisabledSince");
    pw->sp_expire = _nss_registry_strtol(tmpbuf,FALLBACK,&i);
    /* Don't warn in this case since it seems quite normal to not have that set..
     * At least on my system */
    if(tmpbuf != NULL)
        free(tmpbuf);

    tmpbuf = _nss_registry_get_string(REGISTRYUSER, pw->sp_namp,"passwdReserved");
    pw->sp_flag = _nss_registry_strtol(tmpbuf,FALLBACK,&i);
    /* Don't warn in this case since it seems quite normal to not have that set..
     * At least on my system */
    if(tmpbuf != NULL)
        free(tmpbuf);

    /* Woo! this means it was successfull. Go on! tell everyone :) */

    *errnop = 0;
    registryClose();
    return NSS_STATUS_SUCCESS;


    /* Taken from nss-mysql */
out_nomem:
    /* if we're here, that means that the buffer is too small, so
     * we return ERANGE
     */
    *errnop = ERANGE;
    registryClose();
    return NSS_STATUS_TRYAGAIN;

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