Example #1
0
/**@return a backend which gives plugin configuration of the module
 * which is currently point to.
 *
 * @param modules the modules to work with
 * @param errorKey the key to issue warnings and errors to
 */
Backend* elektraBackendOpenModules(KeySet *modules, Key *errorKey)
{
	Backend *backend = elektraBackendAllocate();

	cursor_t save = ksGetCursor (modules);
	KeySet *defaultConfig = ksNew(5,
		keyNew("system/module", KEY_VALUE, "1", KEY_END),
		keyNew("user/module", KEY_VALUE, "1", KEY_END),
		KS_END);
	Key *cur = ksCurrent(modules);

	Plugin *plugin = elektraPluginOpen(keyBaseName(cur), modules, defaultConfig, errorKey);
	if (!plugin)
	{
		/* Error already set in plugin */
		elektraFree(backend);
		return 0;
	}

	Key *mp = keyNew ("system/elektra/modules", KEY_VALUE, "modules", KEY_END);
	keyAddBaseName (mp, keyBaseName(cur));

	backend->getplugins[0] = plugin;
	plugin->refcounter = 1;

	backend->mountpoint = mp;
	keyIncRef(backend->mountpoint);

	ksSetCursor (modules, save);

	return backend;
}
Example #2
0
/**
 * @brief sets mountpoint
 *
 * @param backend where the mountpoint should be set
 * @param elektraConfig the config where the mountpoint can be found
 * @param [out] errorKey the name also has the mountpoint set
 *
 * @pre ksCurrent() is root key
 * @post ksCurrent() is root key
 *
 * @retval -1 if no mountpoint is found or memory allocation problem
 * @retval 0 on success
 */
int elektraBackendSetMountpoint(Backend *backend, KeySet *elektraConfig, Key *errorKey)
{
	Key * root = ksCurrent(elektraConfig);
	Key * searchMountpoint = keyDup(root);
	keyAddBaseName(searchMountpoint, "mountpoint");
	Key * foundMountpoint = ksLookup(elektraConfig, searchMountpoint, 0);
	keyDel (searchMountpoint);
	ksLookup(elektraConfig, root, 0); // reset ksCurrent()

	if (!foundMountpoint)
	{
		ELEKTRA_ADD_WARNINGF(14, errorKey,
			"Could not find mountpoint within root %s",
			keyName(root));
		return -1;
	}

	backend->mountpoint = keyNew("",
			KEY_VALUE, keyBaseName(root), KEY_END);
	elektraKeySetName(backend->mountpoint, keyString(foundMountpoint),
			KEY_CASCADING_NAME | KEY_EMPTY_NAME);

	keySetName(errorKey, keyName(backend->mountpoint));

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

	keyIncRef(backend->mountpoint);
	return 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));
	}
}
Example #4
0
/**
 * Calculate the basename of a key name and put it in @p returned finalizing
 * the string with NULL.
 *
 * Some examples:
 * - basename of @c system/some/keyname is @c keyname
 * - basename of @c "user/tmp/some key" is @c "some key"
 *
 * @param key the key to extract basename from
 * @param returned a pre-allocated buffer to store the basename
 * @param maxSize size of the @p returned buffer
 * @return number of bytes copied to @p returned
 * @retval 1 on empty name
 * @retval -1 on NULL pointers
 * @retval -1 when maxSize is 0 or larger than SSIZE_MAX
 * @see keyBaseName(), keyGetBaseNameSize()
 * @see keyName(), keyGetName(), keySetName()
 * @ingroup keyname
 */
ssize_t keyGetBaseName (const Key * key, char * returned, size_t maxSize)
{
	if (!key) return -1;
	if (!returned) return -1;
	if (!maxSize) return -1;

	if (maxSize > SSIZE_MAX) return -1;
	ssize_t maxSSize = maxSize;

	if (!key->key)
	{
		returned[0] = 0;
		return 1;
	}

	ssize_t baseSize = keyGetBaseNameSize (key);
	if (maxSSize < baseSize)
	{
		return -1;
	}

	const char * baseName = keyBaseName (key);

	if (!baseName)
	{
		return -1;
	}

	strncpy (returned, baseName, baseSize);
	return baseSize;
}
Example #5
0
/**
 * Calculates number of bytes needed to store basename of @p key.
 *
 * Key names that have only root names (e.g. @c "system" or @c "user"
 * or @c "user:domain" ) does not have basenames, thus the function will
 * return 1 bytes to store "".
 *
 * Basenames are denoted as:
 * - @c system/some/thing/basename -> @c basename
 * - @c user:domain/some/thing/base\\/name > @c base\\/name
 *
 * @param key the key object to work with
 * @return size in bytes of @p key's basename including ending NULL
 * @see keyBaseName(), keyGetBaseName()
 * @see keyName(), keyGetName(), keySetName()
 * @ingroup keyname
 */
ssize_t keyGetBaseNameSize (const Key * key)
{
	const char * baseName = keyBaseName (key);
	if (!baseName) return -1;

	return elektraStrLen (baseName);
}
Example #6
0
/**
 @retval 0 if ksCurrent does not hold an array entry
 @retval 1 if the array entry will be used because its the first
 @retval 2 if a new array entry was created
 @retval -1 error in snprintf
 */
static int elektraYajlIncrementArrayEntry (KeySet * ks)
{
	Key * current = ksCurrent (ks);
	const char * baseName = keyBaseName (current);

	if (baseName && *baseName == '#')
	{
		current = keyNew (keyName (current), KEY_END);
		if (!strcmp (baseName, "###empty_array"))
		{
			// get rid of previous key
			keyDel (ksLookup (ks, current, KDB_O_POP));
			// we have a new array entry
			keySetBaseName (current, 0);
			keyAddName (current, "#0");
			ksAppendKey (ks, current);
			return 1;
		}
		else
		{
			// we are in an array
			elektraArrayIncName (current);
			ksAppendKey (ks, current);
			return 2;
		}
	}
	else
	{
		// previous entry indicates this is not an array
		return 0;
	}
}
Example #7
0
static int elektraYajlParseMapKey (void * ctx, const unsigned char * stringVal, yajl_size_type stringLen)
{
	KeySet * ks = (KeySet *)ctx;
	elektraYajlIncrementArrayEntry (ks);

	Key * currentKey = keyNew (keyName (ksCurrent (ks)), KEY_END);
	keySetString (currentKey, 0);

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

#ifdef ELEKTRA_YAJL_VERBOSE
	printf ("elektraYajlParseMapKey stringValue: %s currentKey: %s\n", stringValue, keyName (currentKey));
#endif
	if (currentKey && !strcmp (keyBaseName (currentKey), "___empty_map"))
	{
		// remove old key
		keyDel (ksLookup (ks, currentKey, KDB_O_POP));
		// now we know the name of the object
		keySetBaseName (currentKey, stringValue);
	}
	else
	{
		// we entered a new pair (inside the previous object)
		keySetBaseName (currentKey, stringValue);
	}
	ksAppendKey (ks, currentKey);

	// restore old character in buffer
	stringValue[stringLen] = delim;

	return 1;
}
static CondResult evalMultipleConditions (Key * key, const Key * meta, const Key * suffixList, Key * parentKey, KeySet * returned)
{
	int countSucceeded = 0;
	int countFailed = 0;
	int countNoexpr = 0;
	KeySet * condKS = elektraMetaArrayToKS (key, keyName (meta));
	Key * c;
	CondResult result = FALSE;
	while ((c = ksNext (condKS)) != NULL)
	{
		if (!keyCmp (c, meta)) continue;
		result = evaluateKey (c, suffixList, parentKey, key, returned, CONDITION);
		if (result == TRUE)
			++countSucceeded;
		else if (result == ERROR)
			++countFailed;
		else if (result == NOEXPR)
			++countNoexpr;
	}
	ksDel (condKS);
	if (!strcmp (keyBaseName (meta), "all"))
	{
		// all conditions must evaluate to TRUE
		if (countFailed || countNoexpr)
			return ERROR;
		else
			return TRUE;
	}
	else if (!strcmp (keyBaseName (meta), "any"))
	{
		// at least one conditional must evaluate to TRUE
		if (countSucceeded)
			return TRUE;
		else
			return ERROR;
	}
	else
	{
		// no condition must evaluate to FALSE
		if (countFailed)
			return ERROR;
		else
			return TRUE;
	}
}
Example #9
0
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);
}
Example #10
0
static int isValidArrayKey (Key * key)
{
	Key * copy = keyDup (key);
	do
	{
		if (keyBaseName (copy)[0] == '#')
		{
			if (elektraArrayValidateName (copy) == -1)
			{
				keyDel (copy);
				return 0;
			}
		}
	} while (keySetBaseName (copy, 0) != -1);
	keyDel (copy);
	return 1;
}
Example #11
0
static void test_readFormat (const char * format, const char * fileContent, int numKeys, const char ** keys, const char ** values)
{
	const char * tmpFile = elektraFilename ();
	FILE * fh = fopen (tmpFile, "w");
	if (fh)
	{
		fputs (fileContent, fh);
		fclose (fh);
	}

	Key * parentKey = keyNew ("user/tests/simpleini", KEY_VALUE, tmpFile, KEY_END);
	KeySet * conf = 0;
	if (format)
	{
		conf = ksNew (1, keyNew ("system/format", KEY_VALUE, format, KEY_END), KS_END);
	}
	else
	{
		conf = ksNew (0, KS_END);
	}

	PLUGIN_OPEN ("simpleini");

	KeySet * ks = ksNew (numKeys, KS_END);
	Key * key = 0;

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

	Key * lookup = 0;
	for (int i = 0; i < numKeys; i++)
	{
		lookup = keyNew ("user/tests/simpleini", KEY_END);
		keyAddBaseName (lookup, keys[i]);
		printf ("testing key '%s'\n", keyBaseName (lookup));
		succeed_if ((key = ksLookup (ks, lookup, 0)) != NULL, "key not found");
		succeed_if (strcmp (values[i], keyString (key)) == 0, "value of key did not match");
		keyDel (lookup);
	}

	keyDel (key);
	ksDel (ks);
	keyDel (parentKey);
	PLUGIN_CLOSE ();
}
Example #12
0
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);
}
Example #13
0
/**
 * @brief Increment the name of the key by one
 *
 * Alphabetical order will remain
 *
 * e.g. user/abc/\#9 will be changed to
 *      user/abc/\#_10
 *
 * For the start:
 *      user/abc/\#
 * will be changed to
 *      user/abc/\#0
 *
 * @param key which base name will be incremented
 *
 * @retval -1 on error (e.g. too large array, not validated array)
 * @retval 0 on success
 */
int elektraArrayIncName(Key *key)
{
	const char * baseName = keyBaseName(key);

	int arrayElement = elektraArrayValidateName(key);
	if (arrayElement == -1)
	{
		return -1;
	}

	++baseName; // jump over #
	while(*baseName == '_') // jump over all _
	{
		++baseName;
	}

	kdb_long_long_t oldIndex  = 0;
	if (!arrayElement)
	{
		// we have a start element
		oldIndex = -1;
	}
	else
	{
		if (elektraReadArrayNumber(baseName, &oldIndex) == -1)
		{
			return -1;
		}
	}

	kdb_long_long_t newIndex = oldIndex+1; // we increment by one

	char newName[ELEKTRA_MAX_ARRAY_SIZE];

	elektraWriteArrayNumber(newName, newIndex);
	keySetBaseName(key, newName);

	return 0;
}
Example #14
0
static void validateArray (KeySet * ks, Key * arrayKey, Key * specKey)
{
	Key * tmpArrayParent = keyDup (arrayKey);
	keySetBaseName (tmpArrayParent, 0);
	Key * arrayParent = ksLookup (ks, tmpArrayParent, KDB_O_NONE);
	keyDel (tmpArrayParent);
	if (arrayParent == NULL) return;
	KeySet * ksCopy = ksDup (ks);
	KeySet * subKeys = ksCut (ksCopy, arrayParent);
	Key * cur;
	long validCount = 0;
	while ((cur = ksNext (subKeys)) != NULL)
	{
		if (!keyIsDirectBelow (arrayParent, cur)) continue;
		if (keyBaseName (cur)[0] == '#')
		{
			if (elektraArrayValidateName (cur) == 1)
			{
				++validCount;
				keySetMeta (cur, "spec/internal/valid", "");
			}
			else
			{
				KeySet * invalidCutKS = ksCut (subKeys, cur);
				Key * toMark;
				while ((toMark = ksNext (invalidCutKS)) != NULL)
				{
					if (strcmp (keyName (cur), keyName (toMark))) keySetMeta (toMark, "conflict/invalid", "");
					elektraMetaArrayAdd (arrayParent, "conflict/invalid/hasmember", keyName (toMark));
				}
				ksDel (invalidCutKS);
			}
		}
	}
	ksDel (subKeys);
	ksDel (ksCopy);
	validateArrayRange (arrayParent, validCount, specKey);
}
Example #15
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;
}
Example #16
0
/**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;
}
Example #17
0
static int iniKeyToElektraKey (void *vhandle, const char *section, const char *name, const char *value, unsigned short lineContinuation)
{
	CallbackHandle *handle = (CallbackHandle *)vhandle;
	Key *appendKey = keyDup (handle->parentKey);
	keySetMeta(appendKey, "ini/lastSection", 0);
	if (!section || *section == '\0')
	{
		section = INTERNAL_ROOT_SECTION;
	}
	appendKey = createUnescapedKey(appendKey, section);
	short mergeSections = 0;
	Key *existingKey = NULL;
	if ((existingKey = ksLookup(handle->result, appendKey, KDB_O_NONE)))
	{
		if (keyGetMeta(existingKey, "ini/duplicate"))
		{
			mergeSections = 1;
		}
	}
	setSectionNumber(handle->parentKey, appendKey, handle->result);
	appendKey = createUnescapedKey(appendKey, name);
	existingKey = ksLookup(handle->result, appendKey, KDB_O_NONE);

	if (existingKey)
	{
		//a key with the same name already exists
		if (handle->array)
		{
			//array support is turned on 
			keySetMeta(appendKey, "ini/section", 0);
			if (keyGetMeta(existingKey, "ini/array"))
			{
				//array already exists, appending new key
				const char *lastIndex = keyString(keyGetMeta(existingKey, "ini/array"));
				keyAddBaseName(appendKey, lastIndex);
				keySetMeta(appendKey, "order/parent", 0);
				keySetMeta(appendKey, "ini/array", 0);
				keySetMeta(appendKey, "order", 0);
				if (elektraArrayIncName(appendKey) == 1)
				{
					return -1;
				}
				keySetString(appendKey, value);
				keySetMeta(appendKey, "ini/key", 0);
				ksAppendKey(handle->result, appendKey);
				keySetMeta(existingKey, "ini/array", keyBaseName(appendKey));
				ksAppendKey(handle->result, existingKey);
			}
			else
			{
				//creating a new array
				Key *sectionKey = keyDup(appendKey);
				keyAddName(sectionKey, "..");
				char *origVal = strdup(keyString(existingKey));
				keySetString(appendKey, "");
				keySetMeta(appendKey, "ini/array", "#1");
				keySetMeta(appendKey, "order/parent", keyName(sectionKey));
				setSectionNumber(handle->parentKey, appendKey, handle->result);
				setOrderNumber(handle->parentKey, appendKey);
				keySetMeta(appendKey, "ini/key", "");
				ksAppendKey(handle->result, keyDup(appendKey));
				keySetMeta(appendKey, "ini/key", 0);
				keySetMeta(appendKey, "ini/array", 0);
				keySetMeta(appendKey, "parent", 0);
				keyAddName(appendKey, "#");
				keySetMeta(appendKey, "order", 0);
				if (elektraArrayIncName(appendKey) == -1)
				{
					free(origVal);
					return -1;
				}
				keySetString(appendKey, origVal);
				ksAppendKey(handle->result, keyDup(appendKey));
				free(origVal);
				if (elektraArrayIncName(appendKey) == -1)
				{
					return -1;
				}
				keySetMeta(appendKey, "parent", 0);
				keySetString(appendKey, value);
				ksAppendKey(handle->result, keyDup(appendKey));
				keyDel(appendKey);
				keyDel(sectionKey);
			}
			return 1;
		}
		else if(!lineContinuation)
		{
			ELEKTRA_SET_ERRORF(141, handle->parentKey, "Key: %s\n", name);
			return -1;
		}
	}

	setSectionNumber(handle->parentKey, appendKey, handle->result);
	if (value == NULL)
		keySetMeta(appendKey, "ini/empty", "");
	if (!lineContinuation)
	{
		flushCollectedComment (handle, appendKey);
		keySetString (appendKey, value);
		keySetMeta(appendKey, "ini/key", "");
		ksAppendKey (handle->result, appendKey);
		if (mergeSections)
		{
			keySetMeta(appendKey, "order", 0);
			insertNewKeyIntoExistendOrder(appendKey, handle->result);
		}
		else
		{
			setOrderNumber(handle->parentKey, appendKey);
		}
	}
	else
	{
		existingKey = ksLookup (handle->result, appendKey, KDB_O_NONE);
		keyDel (appendKey);
		/* something went wrong before because this key should exist */
		if (!existingKey) return -1;

		elektraKeyAppendLine(existingKey, value);
	}


	return 1;
}
Example #18
0
/**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;
}
static int csvRead(KeySet *returned, Key *parentKey, char delim, short useHeader, unsigned long fixColumnCount, const char **colNames)
{
    const char *fileName;
    fileName = keyString(parentKey);
    FILE *fp = NULL;
    fp = fopen(fileName, "rb");
    if(!fp)
    {
        ELEKTRA_SET_ERRORF(116, parentKey, "couldn't open file %s\n", fileName);
        return -1;
    }

    unsigned long length = 0;
    length = getLineLength(fp);
    if(length == 0)
    {
        ELEKTRA_ADD_WARNING(118, parentKey, "Empty file");
        fclose(fp);
        return -2;
    }

    char *lineBuffer;
    lineBuffer = elektraMalloc((length * sizeof(char))+1);
    if(!lineBuffer)
    {
        ELEKTRA_SET_ERROR(87, parentKey, "Out of memory");
        return -1;
    }
    if(!fgets(lineBuffer, length, fp))
    {
        ELEKTRA_SET_ERROR(116, parentKey, "Cant read from file");
        return -1;
    }

    unsigned long columns = 0;
    columns = getColumnCount(lineBuffer, delim);
    if(fixColumnCount)
    {
        if(columns != fixColumnCount)
        {
            ELEKTRA_SET_ERROR(117, parentKey, "illegal number of columns in Header line");
            elektraFree(lineBuffer);
            fclose(fp);
            return -1;
        }
    }
    unsigned long colCounter = 0;
    unsigned long lineCounter = 0;
    unsigned long offset = 0;
    char *col;
    char buf[INTSTR_MAX];
    int nr_keys = 1;
    KeySet *header = ksNew(0, KS_END);
    Key *key;

    if(useHeader == 1)
    {
        colCounter = 0;
        offset = 0;
        while((col = parseLine(lineBuffer, delim, offset, parentKey, lineCounter)) != NULL)
        {
            offset += elektraStrLen(col);
            key = keyDup(parentKey);
            if(colNames && (colNames+colCounter))
            {
                keyAddBaseName(key, colNames[colCounter]);
            }
            else
            {
                keyAddBaseName(key, col);
            }
            keySetMeta(key, "csv/order", itostr(buf, colCounter, sizeof(buf)-1));
            ksAppendKey(header, key);
            ++colCounter;
        }
        fseek(fp, 0, SEEK_SET);
    }
    else
    {
        colCounter = 0;
        //if no headerline exists name the columns 0..N where N is the number of columns
        key = keyDup(parentKey);
        keyAddName(key, "#");
        while(colCounter < columns)
        {
            if(elektraArrayIncName(key) == -1)
            {
                elektraFree(lineBuffer);
                keyDel(key);
                ksDel(header);
                fclose(fp);
                return -1;
            }
            keySetMeta(key, "csv/order", itostr(buf, colCounter, sizeof(buf)-1));
            if(colNames && (colNames+colCounter))
                keySetBaseName(key, colNames[colCounter]);
            ksAppendKey(header, keyDup(key));
            ++colCounter;
        }
        keyDel(key);
        if(useHeader == 0)
            fseek(fp, 0, SEEK_SET);
    }
    Key *dirKey;
    Key *cur;
    dirKey = keyDup(parentKey);
    keyAddName(dirKey, "#");
    while(!feof(fp))
    {
        length = getLineLength(fp);
        if(length == 0)
            break;
        if(elektraRealloc((void **)&lineBuffer, (length * sizeof(char))+1) < 0)
        {
            fclose(fp);
            elektraFree(lineBuffer);
            ksDel(header);
            keyDel(dirKey);
            ELEKTRA_SET_ERROR(87, parentKey, "Out of memory");
            return -1;
        }
        fgets(lineBuffer, length, fp);
        if(elektraArrayIncName(dirKey) == -1)
        {
            elektraFree(lineBuffer);
            keyDel(dirKey);
            ksDel(header);
            fclose(fp);
            return -1;
        }
        ++nr_keys;
        offset = 0;
        colCounter = 0;
        char *lastIndex = "#0";
        while((col = parseLine(lineBuffer, delim, offset, parentKey, lineCounter)) != NULL)
        {
            cur = getKeyByOrderNr(header, colCounter);
            offset += elektraStrLen(col);
            key = keyDup(dirKey);
            keyAddBaseName(key, keyBaseName(cur));
            keySetString(key, col);
            keySetMeta(key, "csv/order", itostr(buf, colCounter, sizeof(buf)-1));
            ksAppendKey(returned, key);
            lastIndex = (char *)keyBaseName(key);
            ++nr_keys;
            ++colCounter;
        }
        keySetString(dirKey, lastIndex);
        ksAppendKey(returned, keyDup(dirKey));
        if(colCounter != columns)
        {
            if(fixColumnCount)
            {
                ELEKTRA_SET_ERRORF(117, parentKey, "illegal number of columns in line %lu", lineCounter);
                elektraFree(lineBuffer);
                fclose(fp);
                keyDel(dirKey);
                ksDel(header);
                return -1;
            }
            ELEKTRA_ADD_WARNINGF(118, parentKey, "illegal number of columns in line %lu", lineCounter);
        }
        ++lineCounter;
    }
    key = keyDup(parentKey);
    keySetString(key, keyBaseName(dirKey));
    ksAppendKey(returned, key);
    keyDel(dirKey);
    fclose(fp);
    elektraFree(lineBuffer);
    ksDel(header);
    return 1;
}
Example #20
0
/**
 * @retval 1 and an allocated string of the pluginName if a new plugins should be created.
 * @retval 2 and an allocated string of the referenceName if an old plugin should be used
 * @retval 3 and both if a new plugin should be created and made available for later
 *         back referencing.
 * @retval -1 on error
 */
int elektraProcessPlugin (Key * cur, int * pluginNumber, char ** pluginName, char ** referenceName, Key * errorKey)
{
	const char * fullname = keyBaseName (cur);
	size_t fullsize = keyGetBaseNameSize (cur);

	if (fullname[0] != '#')
	{
		ELEKTRA_ADD_WARNING (18, errorKey, fullname);
		return -1;
	}
	if (fullname[1] < '0' || fullname[1] > '9')
	{
		ELEKTRA_ADD_WARNING (19, errorKey, fullname);
		return -1;
	}
	*pluginNumber = fullname[1] - '0';
	if (*pluginNumber > NR_OF_PLUGINS)
	{
		ELEKTRA_ADD_WARNING (20, errorKey, fullname);
		return -1;
	}

	if (fullname[2] == '#')
	{
		char prefixReferenceName[] = "system/elektra/plugins/";

		/* We have a back reference here */
		if (fullname[fullsize - 2] == '#')
		{
			const char * iter = &fullname[3];
			size_t pluginNameSize = 1; /* For null character */
			size_t referenceNameSize = 0;
			/* We will introduce a new plugin */
			while (*iter != '#')
			{
				++iter;
				++pluginNameSize;
			}

			*pluginName = elektraMalloc (pluginNameSize);
			strncpy (*pluginName, &fullname[3], pluginNameSize);
			(*pluginName)[pluginNameSize - 1] = 0;

			referenceNameSize = fullsize - pluginNameSize - 4;
			++iter; /* advance to one after hash */
			*referenceName = elektraMalloc (referenceNameSize + sizeof (prefixReferenceName));
			strncpy (*referenceName, prefixReferenceName, sizeof (prefixReferenceName));
			strncat (*referenceName, iter, referenceNameSize);
			(*referenceName)[referenceNameSize + sizeof (prefixReferenceName) - 2] = 0;

			return 3;
		}
		else
		{
			/* We reference back to a plugin */

			*referenceName = elektraMalloc (fullsize - 3 + sizeof (prefixReferenceName) - 1);
			strncpy (*referenceName, prefixReferenceName, sizeof (prefixReferenceName));
			strncat (*referenceName, &fullname[3], fullsize - 3);

			return 2;
		}
	}
	else
	{
		*pluginName = elektraMalloc (fullsize - 2); /* don't alloc for #n */
		strncpy (*pluginName, &fullname[2], fullsize - 2);

		return 1;
	}

	/* Should not be reached */
	return 0;
}
Example #21
0
int elektraSortTopology (KeySet * ks, Key ** array)
{
	if (ks == NULL || array == NULL) return -1;
	KeySet * done = ksNew (0, KS_END);
	ksRewind (ks);
	Key * cur;
	ssize_t size = ksGetSize (ks);
	Key * orderCounter = keyNew ("/#", KEY_CASCADING_NAME, KEY_END);
	elektraArrayIncName (orderCounter);
	_adjMatrix adjMatrix[size];
	int i = 0;
	int retVal = 1;
	int depCount = 0;
	Key ** localArray = elektraMalloc (size * sizeof (Key *));
	elektraKsToMemArray (ks, localArray);
	qsort (localArray, size, sizeof (Key *), topCmpOrder);
	for (long j = 0; j < size; ++j)
	{
		adjMatrix[j].key = localArray[j];
		adjMatrix[j].isResolved = 0;
		adjMatrix[j].deps = elektraCalloc (sizeof (unsigned long) * size);
	}
	kdb_octet_t hasOrder = 0;
	if (keyGetMeta (localArray[0], "order")) hasOrder = 1;
	unsigned int unresolved = 0;
	for (int j = 0; j < size; ++j)
	{
		cur = localArray[j];
		KeySet * deps = elektraMetaArrayToKS (cur, "dep");
		keyDel (ksLookupByName (deps, "dep", KDB_O_POP));
		Key * tmpDep;
		switch (ksGetSize (deps))
		{
		case -1:
		{
			// key has no dependencies, give it an order number and add it to list of resolved dependencies
			keySetMeta (cur, "order", keyBaseName (orderCounter));
			elektraArrayIncName (orderCounter);
			ksAppendKey (done, keyDup (cur));
			adjMatrix[j].isResolved = 1;
			ksDel (deps);
			break;
		}
		case 1:
		{
			// only 1 dependency:
			// test if it's reflexive
			tmpDep = ksHead (deps);
			if (!strcmp (keyName (cur), keyString (tmpDep)))
			{
				keySetMeta (cur, "order", keyBaseName (orderCounter));
				elektraArrayIncName (orderCounter);
				ksAppendKey (done, keyDup (cur));
				adjMatrix[j].isResolved = 1;
				ksDel (deps);
				break;
			}
			// if not, fallthrough to normal dependency handling
		}
		default:
		{
			int gotUnresolved = 0;
			while ((tmpDep = ksNext (deps)) != NULL)
			{
				if (!isValidKeyName (keyString (tmpDep)))
				{
					// invalid keyname -> ERROR
					retVal = -1;
					break;
				}
				i = getArrayIndex (tmpDep, adjMatrix, size);
				if (i == -1)
				{
					// key doesn't exist yet but has valid name, ignore it.
					continue;
				}
				else if (i == j)
				{
					// reflexiv depencency, do nothing
				}
				else
				{
					if (!adjMatrix[i].isResolved)
					{
						// unresolved dependency
						adjMatrix[j].deps[i] = 1;
						++gotUnresolved;
						// simple cycle detection
						if (adjMatrix[i].deps[j])
						{
							retVal = 0;
							break;
						}
					}
				}
			}
			if (gotUnresolved)
			{
				adjMatrix[j].isResolved = 0;
				++unresolved;
				// cound unresolved dependencies
				depCount += gotUnresolved;
			}
			ksDel (deps);
			break;
		}
		}
		if (retVal <= 0) break;
	}
	if (retVal <= 0)
	{
		// error or cycle: goto cleanup
		goto TopSortCleanup;
	}

	// resolve all dependencies that can be resolved immediately
	for (int j = 0; j < size; ++j)
	{
		if (adjMatrix[j].isResolved) depCount -= resolveDep (j, adjMatrix, size);
	}

	ssize_t resolved = ksGetSize (done);
	if (((depCount + resolved) >= size) && (unresolved))
	{
		// more dependencies dependencies than keys:
		//  cycle found !
		retVal = 0;
		goto TopSortCleanup;
	}

	if (unresolved)
	{
		int found = 1;
		// we have unresolved dependencies
		for (int j = 0; j < size + 1; ++j)
		{
			// loop until no dependency can be resolved anymore
			if (j == size)
			{
				if (found)
				{
					found = 0;
					j = -1;
					unresolved = 0;
					continue;
				}
				else
					break;
			}
			if (adjMatrix[j].isResolved) continue;
			++unresolved;
			if (hasOrder)
			{
				// resolve by order
				int ret = resolveDeps (j, adjMatrix, size, done, orderCounter);
				if (ret == -1) break;
				j = -1;
				found = 1;
				continue;
			}
			else
			{
				// resolve next possible dependency in keyset
				if (!hasUnresolvedDependencies (j, adjMatrix, size))
				{
					adjMatrix[j].isResolved = 1;
					resolveDep (j, adjMatrix, size);
					keySetMeta (localArray[j], "order", keyBaseName (orderCounter));
					elektraArrayIncName (orderCounter);
					ksAppendKey (done, keyDup (localArray[j]));
					found = 1;
				}
			}
		}
	}
	if (unresolved == 0)
	{
		// everything resolved
		// add dependencies in topological order to array
		elektraKsToMemArray (ks, array);
		qsort (array, size, sizeof (Key *), topCmpOrder);
		retVal = 1;
	}
	else
	{
		// still unresolved dependencies left:
		// there must be a cycle somewhere
		retVal = 0;
	}
TopSortCleanup:
	ksDel (done);
	keyDel (orderCounter);
	elektraFree (localArray);
	for (ssize_t j = 0; j < size; ++j)
	{
		elektraFree (adjMatrix[j].deps);
	}
	return retVal;
}
Example #22
0
/**
 * @internal
 *
 * elektraSortTopology helper
 * resolve all dependencies of the key with the index j in our matrix.
 */
static int resolveDeps (unsigned int j, _adjMatrix * adjMatrix, size_t size, KeySet * done, Key * orderCounter)
{
	unsigned int loops = 0;
	unsigned int frontier[size];
	unsigned int todo = 0;
	for (unsigned int i = 0; i < size; ++i)
	{
		if (adjMatrix[j].deps[i])
		{
			frontier[i] = 1;
			++todo;
		}
		else
		{
			frontier[i] = 0;
		}
	}
	int found = 1;

	// loop until all dependencies are added to frontier
	while (found)
	{
		found = 0;
		for (unsigned int i = 0; i < size; ++i)
		{
			if (!frontier[i]) continue;
			if (hasUnresolvedDependencies (i, adjMatrix, size))
			{
				for (unsigned int k = 0; k < size; ++k)
				{
					if (adjMatrix[i].deps[k])
					{
						if (!frontier[k])
						{
							found = 1;
							++todo;
							frontier[k] = 1;
						}
					}
				}
			}
		}
	}
	if (todo == 0)
	{
		// all dependencies are already resolved, give key an order number and add it to
		// the our list of resolved keys (done)
		adjMatrix[j].isResolved = 1;
		resolveDep (j, adjMatrix, size);
		keySetMeta (adjMatrix[j].key, "order", keyBaseName (orderCounter));
		elektraArrayIncName (orderCounter);
		ksAppendKey (done, keyDup (adjMatrix[j].key));
		return 1;
	}
	unsigned int max_loops = todo;
	for (unsigned int i = 0; todo; ++i)
	{
		if (i == size)
		{
			++loops;
			i = 0;
		}
		if (loops > max_loops) return -1; // more loops than we had unresolved keys -> cycle
		if (!frontier[i]) continue;
		if (!hasUnresolvedDependencies (i, adjMatrix, size))
		{
			resolveDep (i, adjMatrix, size);
			frontier[i] = 0;
			--todo;
			adjMatrix[i].isResolved = 1;
			resolveDep (i, adjMatrix, size);
			keySetMeta (adjMatrix[i].key, "order", keyBaseName (orderCounter));
			elektraArrayIncName (orderCounter);
			ksAppendKey (done, keyDup (adjMatrix[i].key));
		}
	}
	return 1;
}