Exemplo n.º 1
0
/**
 * Compare 2 keys.
 *
 * The returned flags bit array has 1s (differ) or 0s (equal) for each key
 * meta info compared, that can be logically ORed using @c #keyswitch_t flags.
 * @link keyswitch_t::KEY_NAME KEY_NAME @endlink,
 * @link keyswitch_t::KEY_VALUE KEY_VALUE @endlink,
 * @link keyswitch_t::KEY_OWNER KEY_OWNER @endlink,
 * @link keyswitch_t::KEY_COMMENT KEY_COMMENT @endlink,
 * @link keyswitch_t::KEY_UID KEY_UID @endlink,
 * @link keyswitch_t::KEY_GID KEY_GID @endlink,
 * @link keyswitch_t::KEY_MODE KEY_MODE @endlink and
 *
 * @par A very simple example would be
 * @code
Key *key1, *key;
uint32_t changes;

// omited key1 and key2 initialization and manipulation

changes=keyCompare(key1,key2);

if (changes == 0) printf("key1 and key2 are identicall\n");

if (changes & KEY_VALUE)
	printf("key1 and key2 have different values\n");
 
if (changes & KEY_UID)
	printf("key1 and key2 have different UID\n");
 
 *
 * @endcode
 *
 * 
 * @par Example of very powerful specific Key lookup in a KeySet:
 * @code
KDB *handle = kdbOpen();
KeySet *ks=ksNew(0);
Key *base = keyNew ("user/sw/MyApp/something", KEY_END);
Key *current;
uint32_t match;
uint32_t interests;


kdbGetByName(handle, ks, "user/sw/MyApp", 0);

// we are interested only in key type and access permissions
interests=(KEY_TYPE | KEY_MODE);

ksRewind(ks);   // put cursor in the beginning
while ((curren=ksNext(ks))) {
	match=keyCompare(current,base);
	
	if ((~match & interests) == interests)
		printf("Key %s has same type and permissions of base key",keyName(current));

	// continue walking in the KeySet....
}

// now we want same name and/or value
interests=(KEY_NAME | KEY_VALUE);

// we don't really need ksRewind(), since previous loop achieved end of KeySet
ksRewind(ks);
while ((current=ksNext(ks))) {
	match=keyCompare(current,base);

	if ((~match & interests) == interests) {
		printf("Key %s has same name, value, and sync status
			of base key",keyName(current));
	}
	// continue walking in the KeySet....
}

keyDel(base);
ksDel(ks);
kdbClose (handle);
 * @endcode
 * 
 * @return a bit array pointing the differences
 * @param key1 first key
 * @param key2 second key
 * @see #keyswitch_t
 * @ingroup keytest
 */
keyswitch_t keyCompare(const Key *key1, const Key *key2)
{
	if (!key1 && !key2) return 0;
	if (!key1 || !key2) return KEY_NULL;

	keyswitch_t ret=0;
	ssize_t nsize1 = keyGetNameSize(key1);
	ssize_t nsize2 = keyGetNameSize(key2);
	const char *name1 = keyName(key1);
	const char *name2 = keyName(key2);
	const char *comment1 = keyComment(key1);
	const char *comment2 = keyComment(key2);
	const char *owner1 = keyOwner(key1);
	const char *owner2 = keyOwner(key2);
	const void *value1 = keyValue(key1);
	const void *value2 = keyValue(key2);
	ssize_t size1 = keyGetValueSize(key1);
	ssize_t size2 = keyGetValueSize(key2);


	if (keyGetUID(key1) != keyGetUID(key2))  ret|=KEY_UID;
	if (keyGetGID(key1) != keyGetGID(key2))  ret|=KEY_GID;
	if (keyGetMode(key1)!= keyGetMode(key2)) ret|=KEY_MODE;
	if (nsize1 != nsize2)              ret|=KEY_NAME;
	if (strcmp(name1, name2))          ret|=KEY_NAME;
	if (strcmp(comment1, comment2))    ret|=KEY_COMMENT;
	if (strcmp(owner1, owner2))        ret|=KEY_OWNER;
	if (size1 != size2)                ret|=KEY_VALUE;
	if (memcmp(value1, value2, size1)) ret|=KEY_VALUE;

	return ret;
}
Exemplo n.º 2
0
void test_key ()
{
	KeySet * ks;
	Key * cur;
	int counter;

	printf ("Testing Key from xml\n");

	ks = ksNew (0, KS_END);
	exit_if_fail (ksFromXMLfile (ks, srcdir_file ("xmltool/key.xml")) == 0, "ksFromXMLfile(key.xml) failed.");
	counter = 0;
	ksRewind (ks);
	while ((cur = ksNext (ks)))
	{
		counter++;
		/* Prepend key root */
		// snprintf(buf, sizeof(buf), "%s/%s", root, keyName(cur));
		// keySetName(cur, buf);

		/* Make tests ... */
		// printf ("counter: %d - name: %s - value: %s\n", counter, (char*) keyName(cur), (char*)keyValue(cur));
		switch (counter)
		{
		case 1:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/.HiddenBinaryKey") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "BinaryValue") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "Binary key with hidden name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 1, "key is inactive");
			succeed_if (keyIsBinary (cur) == 1, "key is not binary");
			succeed_if (keyGetMode (cur) == 0440, "could not get mode");
			break;
		case 2:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/.HiddenDirectoryKey") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "DirectoryValue") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "Directory key with hidden name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 1, "key is inactive");
			succeed_if (keyIsString (cur) == 1, "key is not string");
			break;
		case 3:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/.HiddenStringKey") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "StringValue") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "String key with hidden name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 1, "key is inactive");
			succeed_if (keyIsString (cur) == 1, "key is not string");
			succeed_if (keyGetUID (cur) == 0, "could not get uid value");
			succeed_if (keyGetGID (cur) == 20, "could not get gid value");
			break;
		case 4:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/PerfectBinaryKey") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "BinaryValue") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "Binary key with standard name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 0, "key is active");
			succeed_if (keyIsBinary (cur) == 1, "key is not binary");
			succeed_if (keyGetGID (cur) == 40, "could not get gid value");
			break;
		case 5:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/PerfectDirectoryKey") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "DirectoryValue") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "Directory key with standard name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 0, "key is active");
			succeed_if (keyIsString (cur) == 1, "key is not string");
			break;
		case 6:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/PerfectStringKey") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "StringValue") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "String key with\nstandard name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 0, "key is active");
			succeed_if (keyIsString (cur) == 1, "key is not string");
			succeed_if (keyGetUID (cur) == 20, "could not get uid value");
			break;
		case 7:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/Ug.ly:Bin@a€ry Key") == 0, "wrong name");
			succeed_if (keyValue (cur) == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "Binary key with ugly name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 0, "key is active");
			succeed_if (keyIsBinary (cur) == 1, "key is not binary");
			succeed_if (keyGetMode (cur) == 230, "could not get mode");
			// <key type="binary" basename="Ug.ly:Bin@a€ry Key"><comment>Binary key with ugly name</comment></key>
			break;
		case 8:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/Ug.ly:Dir@ect€ory Key") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "Directory with ugly name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 0, "key is active");
			succeed_if (keyIsString (cur) == 1, "key is not string");
			// <key type="directory" basename="Ug.ly:Dir@ect€ory Key"><comment>Directory with ugly name</comment></key>
			break;
		case 9:
			succeed_if (strcmp (keyName (cur), "user/tests/filesys/Ug.ly:St@ri€n.g Key") == 0, "wrong name");
			succeed_if (strcmp (keyValue (cur), "With a string value") == 0, "value not correct");
			succeed_if (strcmp (keyComment (cur), "string key with ugly name") == 0, "comment not correct");
			succeed_if (keyIsInactive (cur) == 0, "key is active");
			succeed_if (keyIsString (cur) == 1, "key is not string");
			// <key type="string" basename="Ug.ly:St@ri€n.g Key" value="With a string value"><comment>string key with ugly
			// name</comment></key>
			break;
		}
	}

	ksDel (ks);
}
Exemplo n.º 3
0
/**
 * Output every information of a single key depending on options.
 *
 * The format is not very strict and only intend to be read
 * by human eyes for debugging purposes. Don't rely on the
 * format in your applications.
 *
 * @param k the key object to work with
 * @param stream the file pointer where to send the stream
 * @param options see text above
 * @see ksOutput()
 * @retval 1 on success
 * @retval -1 on allocation errors
 * @ingroup stream
 */
int keyOutput (const Key * k, FILE *stream, option_t options)
{
	time_t t;
	size_t s;
	char * tmc;
	char * str;

	size_t c;
	char * com;

	size_t n;
	char * nam;

	n = keyGetNameSize (k);
	if (n>1)
	{
		nam = (char*) elektraMalloc (n);
		if (nam == NULL) return -1;
		keyGetName (k, nam, n);

		fprintf(stream,"Name[%d]: %s : ", (int)n, nam);

		elektraFree (nam);
	}

	s = keyGetValueSize (k);
	if (options & KEY_VALUE && s>1)
	{
		str = (char*) elektraMalloc (s);
		if (str == NULL) return -1;
		if (keyIsBinary(k))
		{
			/*
			char * bin;
			bin = (char*) elektraMalloc (s*3+1);
			keyGetBinary(k, str, s);
			kdbbEncode (str, s, bin);
			elektraFree (bin);
			*/
			keyGetBinary (k, str, s);
			fprintf(stream,"Binary[%d]: %s : ", (int)s, str);
		} else {
			keyGetString (k, str, s);
			fprintf(stream,"String[%d]: %s : ", (int)s, str);
		}

		elektraFree (str);
	}

	c = keyGetCommentSize (k);
	if (options & KEY_COMMENT && c>1)
	{
		com = (char*) elektraMalloc (c);
		if (com == NULL) return -1;
		keyGetComment (k, com, c);

		fprintf(stream,"Comment[%d]: %s : ", (int)c, com);

		elektraFree (com);
	}


	if (options & KDB_O_SHOWMETA) fprintf(stream," : ");
	if (options & KEY_UID) fprintf(stream,"UID: %d : ", (int)keyGetUID (k));
	if (options & KEY_GID) fprintf(stream,"GID: %d : ", (int)keyGetGID (k));
	if (options & KEY_MODE) fprintf(stream,"Mode: %o : ", (int)keyGetMode (k));

	if (options & KEY_ATIME)
	{
		t=keyGetATime(k);
		tmc = ctime (& t);
		tmc[24] = '\0';
		fprintf(stream,"ATime: %s : ", tmc);
	}

	if (options & KEY_MTIME)
	{
		t=keyGetMTime(k);
		tmc = ctime (& t);
		tmc[24] = '\0';
		fprintf(stream,"MTime: %s : ", tmc);
	}

	if (options & KEY_CTIME)
	{
		t=keyGetCTime(k);
		tmc = ctime (& t);
		tmc[24] = '\0';
		fprintf(stream,"CTime: %s : ", tmc);
	}

	if (options & KDB_O_SHOWFLAGS)
	{
		if (!(options & KDB_O_SHOWMETA)) fprintf(stream, " ");
		fprintf (stream,"Flags: ");
		if (keyIsBinary(k)) fprintf(stream,"b");
		if (keyIsString(k)) fprintf(stream,"s");
		if (keyIsInactive(k)) fprintf(stream,"i");
		if (keyNeedSync(k)) fprintf(stream,"s");
	}

	fprintf(stream,"\n");
	return 1;
}
Exemplo n.º 4
0
/**
 * Same as keyToStream() but tries to strip @p parentSize bytes from
 * @p key name if it matches @p parent .
 *
 * Taking the example from keyToStream(), if @p parent is
 * @c "system/sw/xorg", the generated string is of the form:
 * @verbatim
	<key basename="Monitor/Monitor0/Name"
		type="string" uid="root" gid="root" mode="0600">

		<value>Samsung TFT panel</value>
		<comment>My monitor</comment>
	</key>@endverbatim
 *
 * It usefull to produce more human readable XML output of a key when
 * it is being represented in a context that defines the parent key name.
 * For example:
 *
 * @verbatim
	<keyset parent="user/sw">
		<key basename="kdbedit"..../>
		<key basename="phototools"..../>
		<key basename="myapp"..../>
	</keyset>@endverbatim
 *
 * In the bove example, each @p @<key@> entry was generated by a call to 
 * keyToStreamBasename() having @c "user/sw" as @p parent .
 * 
 * This method is used when ksToStream() is called with
 * KDBOption::KDB_O_HIER option.
 *
 * @param key the key object to work with
 * @param stream the FILE where to send the stream
 * @param parentSize the maximum size of @p parent that will be used.
 *        If 0, the entire @p parent will be used.
 * @param parent the string (or part of it, defined by @p parentSize ) that
 *        will be used to strip from the key name.
 * @param options Some #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_CONDENSED \n
 *   Less human readable, more condensed output
 * - @p option_t::KDB_O_FULLNAME \n
 *   The @p user keys are exported with their full names (including
 *   user domains)
 *
 * @return number of bytes written to output
 */
ssize_t keyToStreamBasename(const Key *key, FILE *stream, const char *parent,
		const size_t parentSize, option_t options) {
	ssize_t written=0;
	char buffer[KDB_MAX_PATH_LENGTH];

	/* Write key name */
	if (parent) {
		/* some logic to see if we should print only the relative basename */
		int found;
		size_t skip=parentSize ? parentSize : elektraStrLen(parent)-1;

		found=memcmp(parent,key->key,skip);
		if (found == 0) {
			while (*(key->key+skip) == KDB_PATH_SEPARATOR) ++skip;

			if (*(key->key+skip) != 0) /* we don't want a null basename */
				written+=fprintf(stream,"<key basename=\"%s\"",
					key->key+skip);
		}
	}

	if (written == 0) { /* no "<key basename=..." was written so far */
		if (options & KDB_O_FULLNAME) {
			keyGetFullName(key,buffer,sizeof(buffer));
			written+=fprintf(stream,"<key name=\"%s\"", buffer);
		} else written+=fprintf(stream,"<key name=\"%s\"", key->key);
	}


	/* Key type
	TODO: xml schema does not output type
	if (options & KDB_O_NUMBERS) {
		written+=fprintf(stream," type=\"%d\"", key->type);
	} else {
		buffer[0]=0;

		if (key->type & KEY_TYPE_DIR) written+=fprintf(stream, " isdir=\"yes\"");
		if (key->type & KEY_TYPE_REMOVE) written+=fprintf(stream, " isremove=\"yes\"");
		if (key->type & KEY_TYPE_BINARY) written+=fprintf(stream, " isbinary=\"yes\"");
	}
	*/

	if (keyGetUID (key) != (uid_t)-1) written+=fprintf(stream," uid=\"%d\"", (int)keyGetUID (key));
	if (keyGetGID (key) != (gid_t)-1) written+=fprintf(stream," gid=\"%d\"", (int)keyGetGID (key));

	if (keyGetMode(key) != KDB_FILE_MODE)
	{
		written+=fprintf(stream," mode=\"0%o\"",
			keyGetMode(key));
	}


	if (!key->data.v && !keyComment(key)) { /* no data AND no comment */
		written+=fprintf(stream,"/>");
		if (!(options & KDB_O_CONDENSED))
			written+=fprintf(stream,"\n\n");
		
		return written; /* end of <key/> */
	} else {
		if (key->data.v) {
			if ((key->dataSize <= 16) && keyIsString (key) && /*TODO: is this for string?*/
					!strchr(key->data.c,'\n')) {

				/* we'll use a "value" attribute instead of a <value> node,
				   for readability, so the cut size will be 16, which is
				   the maximum size of an IPv4 address */

				if (options & KDB_O_CONDENSED) written+=fprintf(stream," ");
				else written+=fprintf(stream,"\n\t");
				
				written+=fprintf(stream,"value=\"%s\"",key->data.c);
				
				if (keyComment(key)) written+=fprintf(stream,">\n");
				else {
					written+=fprintf(stream,"/>");
					if (!(options & KDB_O_CONDENSED))
						written+=fprintf(stream,"\n");
				
					return written;
				}
			} else { /* value is bigger than 16 bytes: deserves own <value> */
				written+=fprintf(stream,">");
				if (!(options & KDB_O_CONDENSED)) written+=fprintf(stream,"\n\n     ");
				
				written+=fprintf(stream,"<value>");
				if (keyIsString(key)) { /*TODO: is this for string?*/
					written+=fprintf(stream,"<![CDATA[");
					fflush(stream);
					/* must chop ending \\0 */
					written+=fwrite(key->data.v,sizeof(char),key->dataSize-1,stream);
					written+=fprintf(stream,"]]>");
				} else {
					/* TODO Binary values 
					char *encoded=elektraMalloc(3*key->dataSize);
					size_t encodedSize;

					written+=fprintf(stream,"\n");
					encodedSize=kdbbEncode(key->data.c,key->dataSize,encoded);
					fflush(stream);
					written+=fwrite(encoded,sizeof(char),encodedSize,stream);
					elektraFree (encoded);
					written+=fprintf(stream,"\n");
					*/
				}
				/* fflush(stream); */
				written+=fprintf(stream,"</value>");
			}
		} else { /* we have no data */
			if (keyComment(key)) {
				written+=fprintf(stream,">");
				if (!(options & KDB_O_CONDENSED))
					written+=fprintf(stream,"\n");
			} else {
				written+=fprintf(stream,"/>");
				if (!(options & KDB_O_CONDENSED))
					written+=fprintf(stream,"\n\n");
			
				return written;
			}
		}
	}

	if (!(options & KDB_O_CONDENSED)) {
		written+=fprintf(stream,"\n");
		if (keyComment(key)) written+=fprintf(stream,"     ");
	}

	if (keyComment(key)) {
		written+=fprintf(stream,"<comment><![CDATA[%s]]></comment>", keyComment(key));
		if (!(options & KDB_O_CONDENSED))
			written+=fprintf(stream,"\n");
	}

	written+=fprintf(stream,"</key>");

	if (!(options & KDB_O_CONDENSED))
		written+=fprintf(stream,"\n\n");

	return written;
}