예제 #1
0
static int csvWrite(KeySet *returned, Key *parentKey, char delim, short useHeader)
{
    FILE *fp;
    fp = fopen(keyString(parentKey), "w");
    if(!fp)
    {
        ELEKTRA_SET_ERROR_SET(parentKey);
        return -1;
    }

    keyDel(ksLookup(returned, parentKey, KDB_O_POP));

    unsigned long colCounter = 0;
    unsigned long columns = 0;
    unsigned long lineCounter = 0;
    Key *cur;
    KeySet *toWriteKS;
    Key *toWrite;
    while((cur = ksNext(returned)) != NULL)
    {
        if(keyRel(parentKey, cur) != 1)
            continue;
        if(useHeader)
        {
            useHeader = 0;
            continue;
        }
        toWriteKS = ksCut(returned, cur);
        colCounter = 0;
        while(1)
        {
            toWrite = getKeyByOrderNr(toWriteKS, colCounter);
            if(!toWrite)
                break;
            if(colCounter)
                fprintf(fp, "%c", delim);
            ++colCounter;
            fprintf(fp, "%s", keyString(toWrite));
        }
        ksDel(toWriteKS);
        fprintf(fp, "\n");
        if(columns == 0)
        {
            columns = colCounter;
        }

        if(colCounter != columns)
        {
            ELEKTRA_SET_ERRORF(117, parentKey, "illegal number of columns in line %lu\n", lineCounter);
            fclose(fp);
            return -1;
        }
        ++lineCounter;
    }
    fclose(fp);
    return 1;
}
예제 #2
0
/**
 * @retval 1 if one of the backends in split has all
 *          keys below parentKey
 * @retval 0 if parentKey == 0 or there are keys below
 *          or same than parentKey which do not fit
 *          in any of split keysets
 * @param split the split object to work with
 * @param parentKey the key which relation is searched for
 * @ingroup split
 */
int elektraSplitSearchRoot (Split * split, Key * parentKey)
{
	if (!parentKey) return 0;

	for (size_t i = 0; i < split->size; ++i)
	{
		if (keyRel (split->parents[i], parentKey) >= 0) return 1;
	}

	return 0;
}
예제 #3
0
static void writeHostsEntry(Key* key, KeySet* returned, FILE* fp)
{
	fprintf (fp, "%s\t%s", (char*) keyValue (key), (char*) keyBaseName (key));
	/* position the cursor at the current key and
	 * iterate over its subkeys
	 */
	ksLookup (returned, key, KDB_O_NONE);
	Key* alias;
	while ((alias = ksNext (returned)) != 0)
	{
		if (keyRel (key, alias) < 1) break;

		fprintf (fp, " %s", (char*) keyBaseName (alias));
	}
}
예제 #4
0
파일: backend.c 프로젝트: beku/libelektra
/**Builds a backend out of the configuration supplied
 * from:
 *
@verbatim
system/elektra/mountpoints/<name>
@endverbatim
 *
 * The root key must be like the above example. You do
 * not need to rewind the keyset. But every key must be
 * below the root key.
 *
 * The internal consistency will be checked in this
 * function. If necessary parts are missing, like
 * no plugins, they cant be loaded or similar 0
 * will be returned.
 *
 * ksCut() is perfectly suitable for cutting out the
 * configuration like needed.
 *
 * @note The given KeySet will be deleted within the function,
 * don't use it afterwards.
 *
 * @param elektraConfig the configuration to work with.
 *        It is used to build up this backend.
 * @param modules used to load new modules or get references
 *        to existing one
 * @return a pointer to a freshly allocated backend
 *         this could be the requested backend or a so called
 *         "missing backend".
 * @retval 0 if out of memory
 * @ingroup backend
 */
Backend* elektraBackendOpen(KeySet *elektraConfig, KeySet *modules, Key *errorKey)
{
	Key * cur;
	Key * root;
	KeySet *referencePlugins = 0;
	KeySet *systemConfig = 0;
	int failure = 0;

	referencePlugins = ksNew(0, KS_END);
	ksRewind(elektraConfig);

	root = ksNext (elektraConfig);

	Backend *backend = elektraBackendAllocate();

	while ((cur = ksNext(elektraConfig)) != 0)
	{
		if (keyRel (root, cur) == 1)
		{
			// direct below root key
			KeySet *cut = ksCut (elektraConfig, cur);
			if (!strcmp(keyBaseName(cur), "config"))
			{
				systemConfig = elektraRenameKeys(cut, "system");
				ksDel (cut);
			}
			else if (!strcmp(keyBaseName(cur), "getplugins"))
			{
				if (elektraProcessPlugins(backend->getplugins, modules, referencePlugins,
							cut, systemConfig, errorKey) == -1)
				{
					if (!failure) ELEKTRA_ADD_WARNING(13, errorKey, "elektraProcessPlugins for get failed");
					failure = 1;
				}
			}
			else if (!strcmp(keyBaseName(cur), "mountpoint"))
			{
				backend->mountpoint = keyNew("",
						KEY_VALUE, keyBaseName(root), KEY_END);
				elektraKeySetName(backend->mountpoint, keyString(cur),
						KEY_CASCADING_NAME | KEY_EMPTY_NAME);

				if (!backend->mountpoint)
				{
					if (!failure) ELEKTRA_ADD_WARNINGF(14, errorKey,
						"Could not create mountpoint with name %s and value %s",
						keyString(cur), keyBaseName(root));
					failure = 1;
				}

				keyIncRef(backend->mountpoint);
				ksDel (cut);
			}
			else if (!strcmp(keyBaseName(cur), "setplugins"))
			{
				if (elektraProcessPlugins(backend->setplugins, modules, referencePlugins,
							cut, systemConfig, errorKey) == -1)
				{
					if (!failure) ELEKTRA_ADD_WARNING(15, errorKey, "elektraProcessPlugins for set failed");
					failure = 1;
				}
			}
			else if (!strcmp(keyBaseName(cur), "errorplugins"))
			{
				if (elektraProcessPlugins(backend->errorplugins, modules, referencePlugins,
							cut, systemConfig, errorKey) == -1)
				{
					if (!failure) ELEKTRA_ADD_WARNING(15, errorKey, "elektraProcessPlugins for error failed");
					failure = 1;
				}
			} else {
				// no one cares about that config
				if (!failure) ELEKTRA_ADD_WARNING(16, errorKey, keyBaseName(cur));
				ksDel (cut);
			}
		}
	}

	if (failure)
	{
		Backend *tmpBackend = elektraBackendOpenMissing(backend->mountpoint);
		elektraBackendClose(backend, errorKey);
		backend = tmpBackend;
	}

	ksDel (systemConfig);
	ksDel (elektraConfig);
	ksDel (referencePlugins);

	return backend;
}
예제 #5
0
/**
 * Walks through kdb->split and adds all backends below parentKey to split.
 *
 * Sets syncbits to 2 if it is a default or root backend (which needs splitting).
 * The information is copied from kdb->split.
 *
 * @pre split needs to be empty, directly after creation with elektraSplitNew().
 *
 * @pre there needs to be a valid defaultBackend
 *      but its ok not to have a trie inside KDB.
 *
 * @pre parentKey must be a valid key! (could be implemented more generally,
 *      but that would require splitting up of keysets of the same backend)
 *
 * @param split will get all backends appended
 * @param kdb the handle to get information about backends
 * @param parentKey the information below which key the backends are from interest
 * @ingroup split
 * @retval 1 always
 */
int elektraSplitBuildup (Split * split, KDB * kdb, Key * parentKey)
{
	/* For compatibility reasons invalid names are accepted, too.
	 * This solution is faster than checking the name of parentKey
	 * every time in loop.
	 * The parentKey might be null in some unit tests, so also check
	 * for this. */
	const char * name = keyName (parentKey);
	if (!parentKey || !name || !strcmp (name, "") || !strcmp (name, "/"))
	{
		parentKey = 0;
	}
	else if (name[0] == '/')
	{
		Key * key = keyNew (0, KEY_END);
		for (elektraNamespace ins = KEY_NS_FIRST; ins <= KEY_NS_LAST; ++ins)
		{
			if (!elektraKeySetNameByNamespace (key, ins)) continue;
			keyAddName (key, keyName (parentKey));
			elektraSplitBuildup (split, kdb, key);
		}
		keyDel (key);
		return 1;
	}

	/* Returns the backend the key is in or the default backend
	   otherwise */
	Backend * backend = elektraMountGetBackend (kdb, parentKey);

#if DEBUG && VERBOSE
	printf (" with parent %s\n", keyName (parentKey));
#endif
	for (size_t i = 0; i < kdb->split->size; ++i)
	{
#if DEBUG && VERBOSE
		printf ("  %zu with parent %s\n", i, keyName (kdb->split->parents[i]));
#endif
		if (!parentKey)
		{
#if DEBUG && VERBOSE
			printf ("   def add %s\n", keyName (kdb->split->parents[i]));
#endif
			/* Catch all: add all mountpoints */
			elektraSplitAppend (split, kdb->split->handles[i], keyDup (kdb->split->parents[i]), kdb->split->syncbits[i]);
		}
		else if (backend == kdb->split->handles[i] && keyRel (kdb->split->parents[i], parentKey) >= 0)
		{
#if DEBUG && VERBOSE
			printf ("   exa add %s\n", keyName (kdb->split->parents[i]));
#endif
			/* parentKey is exactly in this backend, so add it! */
			elektraSplitAppend (split, kdb->split->handles[i], keyDup (kdb->split->parents[i]), kdb->split->syncbits[i]);
		}
		else if (keyRel (parentKey, kdb->split->parents[i]) >= 0)
		{
#if DEBUG && VERBOSE
			printf ("   rel add %s\n", keyName (kdb->split->parents[i]));
#endif
			/* this backend is completely below the parentKey, so lets add it. */
			elektraSplitAppend (split, kdb->split->handles[i], keyDup (kdb->split->parents[i]), kdb->split->syncbits[i]);
		}
	}

	return 1;
}
예제 #6
0
파일: backend.c 프로젝트: tryge/libelektra
/**Builds a backend out of the configuration supplied
 * from:
 *
@verbatim
system/elektra/mountpoints/<name>
@endverbatim
 *
 * The root key must be like the above example. You do
 * not need to rewind the keyset. But every key must be
 * below the root key.
 *
 * The internal consistency will be checked in this
 * function. If necessary parts are missing, like
 * no plugins, they cant be loaded or similar 0
 * will be returned.
 *
 * ksCut() is perfectly suitable for cutting out the
 * configuration like needed.
 *
 * @note The given KeySet will be deleted within the function,
 * don't use it afterwards.
 *
 * @param elektraConfig the configuration to work with.
 *        It is used to build up this backend.
 * @param modules used to load new modules or get references
 *        to existing one
 * @param errorKey the key where an error and warnings are added
 *
 * @return a pointer to a freshly allocated backend
 *         this could be the requested backend or a so called
 *         "missing backend".
 * @retval 0 if out of memory
 * @ingroup backend
 */
Backend* elektraBackendOpen(KeySet *elektraConfig, KeySet *modules, Key *errorKey)
{
	Key * cur;
	KeySet *referencePlugins = 0;
	KeySet *systemConfig = 0;
	int failure = 0;

	referencePlugins = ksNew(0, KS_END);
	ksRewind(elektraConfig);

	Key * root = ksNext (elektraConfig);

	Backend *backend = elektraBackendAllocate();
	if (elektraBackendSetMountpoint(backend, elektraConfig, errorKey) == -1)
	{	// warning already set
		failure = 1;
	}

	while ((cur = ksNext(elektraConfig)) != 0)
	{
		if (keyRel (root, cur) == 1)
		{
			// direct below root key
			KeySet *cut = ksCut (elektraConfig, cur);
			if (!strcmp(keyBaseName(cur), "config"))
			{
				systemConfig = elektraRenameKeys(cut, "system");
				ksDel (cut);
			}
			else if (!strcmp(keyBaseName(cur), "errorplugins"))
			{
				if (elektraProcessPlugins(backend->errorplugins, modules, referencePlugins,
							cut, systemConfig, errorKey) == -1)
				{
					if (!failure) ELEKTRA_ADD_WARNING(15, errorKey, "elektraProcessPlugins for error failed");
					failure = 1;
				}
			}
			else if (!strcmp(keyBaseName(cur), "getplugins"))
			{
				if (elektraProcessPlugins(backend->getplugins, modules, referencePlugins,
							cut, systemConfig, errorKey) == -1)
				{
					if (!failure) ELEKTRA_ADD_WARNING(13, errorKey, "elektraProcessPlugins for get failed");
					failure = 1;
				}
			}
			else if (!strcmp(keyBaseName(cur), "mountpoint"))
			{
				ksDel (cut); // already handled by elektraBackendSetMountpoint
				continue;
			}
			else if (!strcmp(keyBaseName(cur), "setplugins"))
			{
				if (elektraProcessPlugins(backend->setplugins, modules, referencePlugins,
							cut, systemConfig, errorKey) == -1)
				{
					if (!failure) ELEKTRA_ADD_WARNING(15, errorKey, "elektraProcessPlugins for set failed");
					failure = 1;
				}
			} else {
				// no one cares about that config
				if (!failure) ELEKTRA_ADD_WARNING(16, errorKey, keyBaseName(cur));
				ksDel (cut);
			}
		}
	}

	if (failure)
	{
		Backend *tmpBackend = elektraBackendOpenMissing(backend->mountpoint);
		elektraBackendClose(backend, errorKey);
		backend = tmpBackend;
	}

	ksDel (systemConfig);
	ksDel (elektraConfig);
	ksDel (referencePlugins);

	return backend;
}
예제 #7
0
/**
 * Load a plugin.
 *
 * The array of plugins must be set to 0.
 * Its length is NR_OF_PLUGINS.
 *
 * systemConfig will only be used, not deleted.
 *
 * @param config the config with the information how the
 *        plugins should be put together
 * @param systemConfig the shared (system) config for the plugins.
 *        Every plugin additional get this config.
 *
 * @retval -1 on failure
 */
int elektraProcessPlugins (Plugin ** plugins, KeySet * modules, KeySet * referencePlugins, KeySet * config, KeySet * systemConfig,
			   Key * errorKey)
{
	Key * root;
	Key * cur;

	ksRewind (config);

	root = ksNext (config);

	while ((cur = ksNext (config)) != 0)
	{
		if (keyRel (root, cur) == 1)
		{
			char * pluginName = 0;
			char * referenceName = 0;
			int pluginNumber = 0;

			Key * key;

			if (elektraProcessPlugin (cur, &pluginNumber, &pluginName, &referenceName, errorKey) == -1)
			{
				elektraFree (pluginName);
				elektraFree (referenceName);
				ksDel (config);
				return -1;
			}


			if (pluginName)
			{
				key = keyDup (cur);
				keyAddBaseName (key, "config");
				KeySet * cutConfig = ksCut (config, key);
				keyDel (key);

				KeySet * pluginConfig = elektraRenameKeys (cutConfig, "user");
				ksDel (cutConfig);
				if (!pluginConfig) return -1;
				ksAppend (pluginConfig, systemConfig);
				ksRewind (pluginConfig); /* TODO: bug ksAppend invalidates cursor */

				/* case 1, we create a new plugin,
				   note that errorKey is not passed here, because it would set error information
				   but we only want a warning instead. */
				plugins[pluginNumber] = elektraPluginOpen (pluginName, modules, pluginConfig, errorKey);
				if (!plugins[pluginNumber])
				{
					ELEKTRA_ADD_WARNING (64, errorKey, pluginName);
					/* Loading plugin did not work */
					elektraFree (pluginName);
					elektraFree (referenceName);
					ksDel (config);
					return -1;
				}

				/* case 2, we label it for later use */
				if (referenceName)
					ksAppendKey (referencePlugins,
						     keyNew (referenceName, KEY_BINARY, KEY_SIZE, sizeof (plugins[pluginNumber]), KEY_VALUE,
							     &plugins[pluginNumber], KEY_END));
			}
			else
			{
				/* case 3, we use an existing plugin */
				Key * lookup = ksLookup (referencePlugins, keyNew (referenceName, KEY_END), KDB_O_DEL);
				if (!lookup)
				{
					ELEKTRA_ADD_WARNING (65, errorKey, referenceName);
					/* Getting a reference plugin at a previous stage did not work.
					Note that this check is necessary, because loading the plugin could
					fail for example at errorplugins and at a later point, for example
					at setplugins it is tried to refer to that.*/
					elektraFree (referenceName);
					ksDel (config);
					return -1;
				}
				plugins[pluginNumber] = *(Plugin **)keyValue (lookup);
				++plugins[pluginNumber]->refcounter;
			}
			elektraFree (pluginName);
			elektraFree (referenceName);
		}
		else
		{
			ELEKTRA_ADD_WARNING (21, errorKey, keyString (cur));
		}
	}

	ksDel (config);
	return 0;
}
예제 #8
0
static int listParseConfiguration (Placements * placements, KeySet * config)
{
	Key * cur;
	Key * key = ksLookupByName (config, "/plugins", 0);
	KeySet * cutKS = ksCut (config, key);
	ksRewind (cutKS);
	if (ksGetSize (cutKS) < 2) return 0;
	int rc = 0;
	while ((cur = ksNext (cutKS)) != NULL)
	{
		if (keyRel (key, cur) != 1)
		{
			continue;
		}
		if (keyBaseName (cur)[0] == '#')
		{
			if (strcmp (lastIndex, keyBaseName (cur)) < 0)
			{
				snprintf (lastIndex, ELEKTRA_MAX_ARRAY_SIZE, "%s", keyBaseName (cur));
			}
		}
		Key * sub;
		Key * lookup = keyDup (cur);
		keyAddBaseName (lookup, "placements");
		keyAddBaseName (lookup, "set");
		sub = ksLookup (cutKS, lookup, 0);
		if (sub)
		{
			const char * setString = keyString (sub);
			const char * setStrings[] = { "presetstorage", "presetcleanup", "precommit", "postcommit" };
			SetPlacements setPlacement = preSetStorage;
			while (setPlacement != setEnd)
			{
				if (strstr (setString, setStrings[setPlacement]))
				{
					rc = 1;
					ksAppendKey (placements->setKS[setPlacement], keyDup (cur));
				}
				++setPlacement;
			}
		}
		keySetBaseName (lookup, "get");
		sub = ksLookup (cutKS, lookup, 0);
		if (sub)
		{
			const char * getString = keyString (sub);
			const char * getStrings[] = { "pregetstorage", "postgetstorage", "postgetcleanup" };
			GetPlacements getPlacement = preGetStorage;
			while (getPlacement != getEnd)
			{
				if (strstr (getString, getStrings[getPlacement]))
				{
					rc = 1;
					ksAppendKey (placements->getKS[getPlacement], keyDup (cur));
				}
				++getPlacement;
			}
		}
		keySetBaseName (lookup, "error");
		sub = ksLookup (cutKS, lookup, 0);
		if (sub)
		{
			const char * errString = keyString (sub);
			const char * errStrings[] = { "prerollback", "postrollback" };
			ErrPlacements errPlacement = preRollback;
			while (errPlacement != errEnd)
			{
				if (strstr (errString, errStrings[errPlacement]))
				{
					rc = 1;
					ksAppendKey (placements->errKS[errPlacement], keyDup (cur));
				}
				++errPlacement;
			}
		}
		keyDel (lookup);
	}
	ksDel (cutKS);
	return rc;
}