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

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

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

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

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

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

	elektraFree (keyArray);
	ksDel (ks);
}
Beispiel #2
0
static int saveTree (augeas * augeasHandle, KeySet * ks, const char * lensPath, Key * parentKey)
{
	int ret = 0;

	size_t prefixSize = keyGetNameSize (parentKey) - 1;
	size_t arraySize = ksGetSize (ks);
	Key ** keyArray = calloc (ksGetSize (ks), sizeof (Key *));
	ret = elektraKsToMemArray (ks, keyArray);

	if (ret < 0) goto memoryerror;

	qsort (keyArray, arraySize, sizeof (Key *), keyCmpOrderWrapper);

	/* convert the Elektra KeySet to an Augeas tree */
	for (size_t i = 0; i < arraySize; i++)
	{
		Key * key = keyArray[i];
		char * nodeName;
		ret = asprintf (&nodeName, AUGEAS_TREE_ROOT "%s", (keyName (key) + prefixSize));

		if (ret < 0) goto memoryerror;

		aug_set (augeasHandle, nodeName, keyString (key));
		elektraFree (nodeName);
	}

	elektraFree (keyArray);

	/* remove keys not present in the KeySet */
	struct OrphanSearch * data = elektraMalloc (sizeof (struct OrphanSearch));

	if (!data) return -1;

	data->ks = ks;
	data->parentKey = parentKey;

	ret = foreachAugeasNode (augeasHandle, AUGEAS_TREE_ROOT, &removeOrphan, data);

	elektraFree (data);

	/* build the tree */
	ret = aug_text_retrieve (augeasHandle, lensPath, AUGEAS_CONTENT_ROOT, AUGEAS_TREE_ROOT, AUGEAS_OUTPUT_ROOT);

	if (ret < 0)
	{
		/* report the augeas specific error */
		ELEKTRA_SET_ERROR (85, parentKey, getAugeasError (augeasHandle));
	}

	return ret;

memoryerror:
	elektraFree (keyArray);
	ELEKTRA_SET_ERROR (87, parentKey, "Unable to allocate memory while saving the augeas tree");
	return -1;
}
Beispiel #3
0
static int saveTree(augeas* augeasHandle, KeySet* ks, const char* lensPath,
		Key *parentKey)
{
	int ret = 0;

	size_t prefixSize = keyGetNameSize (parentKey) - 1;
	size_t arraySize = ksGetSize (ks);
	Key **keyArray = calloc (ksGetSize(ks), sizeof (Key *));
	ret = elektraKsToMemArray (ks, keyArray);

	if (ret < 0)
	{
		free (keyArray);
		return -1;
	}

	qsort (keyArray, arraySize, sizeof(Key *), keyCmpOrderWrapper);

	/* convert the Elektra KeySet to an Augeas tree */
	for (size_t i = 0; i < arraySize; i++)
	{
		Key *key = keyArray[i];
		char *nodeName;
		asprintf (&nodeName, AUGEAS_TREE_ROOT "%s",
				(keyName (key) + prefixSize));
		aug_set (augeasHandle, nodeName, keyString (key));
		free (nodeName);
	}

	free (keyArray);

	/* remove keys not present in the KeySet */
	struct OrphanSearch *data = malloc (sizeof(struct OrphanSearch));

	if (!data) return -1;

	data->ks = ks;
	data->parentKey = parentKey;

	foreachAugeasNode (augeasHandle, AUGEAS_TREE_ROOT, &removeOrphan, data);

	free (data);

	/* build the tree */
	ret = aug_text_retrieve (augeasHandle, lensPath, AUGEAS_CONTENT_ROOT,
	AUGEAS_TREE_ROOT, AUGEAS_OUTPUT_ROOT);

	return ret;
}
Beispiel #4
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;
}