Example #1
0
/**
 * Writes to @p stream an XML version of the @p ks object.
 *
 * String generated is of the form:
 * @verbatim
<keyset>
<key name=...>...</key>
<key name=...>...</key>
<key name=...>...</key>

</keyset>
 * @endverbatim
 *
 * or if KDB_O_HIER is used, the form will be:
 * @verbatim
<keyset parent="user/smallest/parent/name">

<key basename=...>...</key>
<key name=...>...</key> <!-- a key thats not under this keyset's parent -->
<key basename=...>...</key>

</keyset>
 * @endverbatim
 *
 * KDB_O_HEADER will additionally generate a header like:
 * @verbatim
<?xml version="1.0" encoding="UTF-8"?>
<!-- Generated by Elektra API. Total of n keys. -->
<keyset xmlns="http://www.libelektra.org"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.libelektra.org elektra.xsd">
 * @endverbatim
 *
 * @param ks the KeySet to serialise
 * @param stream where to write output: a file or stdout
 * @param options accepted #option_t ORed:
 * - @p option_t::KDB_O_NUMBERS \n
 *   Do not convert UID and GID into user and group names.
 * - @p option_t::KDB_O_FULLNAME \n
 *   The @c user keys are exported with their full names (including
 *   user domains)
 * - @p option_t::KDB_O_CONDENSED \n
 *   Less human readable, more condensed output.
 * - @p option_t::KDB_O_XMLHEADERS \n
 *   Exclude the correct XML headers in the output. If not used, the
 *   &lt;?xml?&gt; and schema info inside the &lt;keyset&gt; object will not be generated.
 * - @p option_t::KDB_O_HIER \n
 *   Will generate a &lt;keyset&gt; node containing a @c parent attribute, and
 *   &lt;key&gt; nodes with a @c basename relative to that @c parent. The @c parent
 *   is calculated by taking the smallest key name in the keyset, so it is a
 *   good idea to have only related keys on the keyset. Otherwise, a valid
 *   consistent XML document still will be generated with regular absolute
 *   @c name attribute for the &lt;key&gt; nodes, due to a
 *   clever keyToStreamBasename() implementation.
 *
 * @see keyToStream()
 * @see commandList() for usage example
 * @return number of bytes written to output, or -1 if some error occurs
 * @param ks The keyset to output
 * @param stream the file pointer where to send the stream
 * @param options see above text
 */
ssize_t ksToStream(const KeySet *ks, FILE* stream, option_t options)
{
	size_t written=0;
	Key *key=0;
	char *codeset = "UTF-8";
	KeySet *cks = ksDup (ks);

	ksRewind (cks);

	if (options & KDB_O_HEADER) {
		written+=fprintf(stream,"<?xml version=\"1.0\" encoding=\"%s\"?>",
			codeset);
		if (~options & KDB_O_CONDENSED)
			written+=fprintf(stream,
					"\n<!-- Generated by Elektra API. Total of %d keys. -->\n",(int)cks->size);
		if (~options & KDB_O_CONDENSED)
			written+=fprintf(stream,"<keyset xmlns=\"http://www.libelektra.org\"\n"
					"\txmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n"
					"\txsi:schemaLocation=\"http://www.libelektra.org elektra.xsd\"\n");
		else
			written+=fprintf(stream,"<keyset xmlns=\"http://www.libelektra.org\""
					" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""
					" xsi:schemaLocation=\"http://www.libelektra.org elektra.xsd\"");
	} else written+=fprintf(stream,"<keyset");

	if (options & KDB_O_HIER) {
		char commonParent[KDB_MAX_PATH_LENGTH];

		ksGetCommonParentName(cks,commonParent,sizeof(commonParent));
	
		if (commonParent[0]) {
			written+=fprintf(stream,"        parent=\"%s\">\n",
				commonParent);
			ksRewind (cks);
			while ((key=ksNext (cks)) != 0)
				written+=keyToStreamBasename(key,stream,commonParent,0,options);
		} else {
			written+=fprintf(stream,">\n");
			ksRewind (cks);
			while ((key=ksNext (cks)) != 0)
				written+=keyToStream(key,stream,options);
		}
	} else { /* No KDB_O_HIER*/
		written+=fprintf(stream,">\n");
		ksRewind (cks);
		while ((key=ksNext (cks)) != 0)
			written+=keyToStream(key,stream,options);
	}
	
	written+=fprintf(stream,"</keyset>\n");
	ksDel (cks);
	return written;
}
static void test_ksCommonParentName()
{
	char ret [MAX_SIZE+1];
	KeySet *ks = ksNew (10,
		keyNew("system/sw/xorg/Monitors/Monitor1/vrefresh",0),
		keyNew("system/sw/xorg/Monitors/Monitor1/hrefresh",0),
		keyNew("system/sw/xorg/Monitors/Monitor2/vrefresh",0),
		keyNew("system/sw/xorg/Monitors/Monitor2/hrefresh",0),
		keyNew("system/sw/xorg/Devices/Device1/driver",0),
		keyNew("system/sw/xorg/Devices/Device1/mode",0),KS_END);

	printf ("Test common parentname\n");

	succeed_if (ksGetCommonParentName(ks, ret, MAX_SIZE) > 0, "could not find correct parentname");
	succeed_if_same_string (ret, "system/sw/xorg");
	ksDel (ks);

	ks = ksNew (10,
		keyNew("system",0),
		keyNew("user",0),KS_END);
	succeed_if (ksGetCommonParentName(ks, ret, MAX_SIZE) == 0, "could find correct parentname");
	succeed_if_same_string (ret, "");
	ksDel (ks);

	ks = ksNew (10,
		keyNew("system/some/thing",0),
		keyNew("system/other/thing",0), KS_END);
	succeed_if (ksGetCommonParentName(ks, ret, MAX_SIZE) == 7, "could find correct parentname");
	succeed_if_same_string (ret, "system");
	ksDel (ks);

	ks = ksNew (10,
		keyNew("system/here/in/deep/goes/ok/thing",0),
		keyNew("system/here/in/deep/goes/ok/other/thing",0),
		KS_END);
	succeed_if (ksGetCommonParentName(ks, ret, MAX_SIZE) > 0, "could find correct parentname");
	succeed_if_same_string (ret, "system/here/in/deep/goes/ok");
	ksDel (ks);

	ks = ksNew (10,
		keyNew("system/here/in/deep/goes/ok/thing",0),
		keyNew("system/here/in/deep/goes/ok/other/thing",0),
		keyNew("user/unique/thing",0),KS_END);
	succeed_if (ksGetCommonParentName(ks, ret, MAX_SIZE) == 0, "could find correct parentname");
	succeed_if_same_string (ret, "");
	ksDel (ks);

	ks = ksNew (10,
		keyNew("user/unique/thing",0),KS_END);
	succeed_if (ksGetCommonParentName(ks, ret, MAX_SIZE) > 0, "could find correct parentname");
	succeed_if_same_string (ret, "user/unique/thing");
	ksDel (ks);
}