/** * 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; }
/** * @internal * * 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_META KEY_META @endlink (will be set in addition to owner and comment), * * @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 Key *base = keyNew ("/sw/MyApp/something", KEY_END); KDB *handle = kdbOpen(base); KeySet *ks=ksNew(0, KS_END); Key *current; uint32_t match; uint32_t interests; kdbGet(handle, ks, base); // 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.... } ksDel(ks); kdbClose (handle, base); keyDel(base); * @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 Key * comment1 = keyGetMeta (key1, "comment"); const Key * comment2 = keyGetMeta (key2, "comment"); 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); // TODO: might be (binary) by chance if (strcmp (keyString (comment1), keyString (comment2))) ret |= KEY_COMMENT; if (strcmp (owner1, owner2)) ret |= KEY_OWNER; if (keyCompareMeta (key1, key2)) ret |= KEY_META; if (nsize1 != nsize2) ret |= KEY_NAME; else if (!name1 || !name2) ret |= KEY_NAME; else if (strcmp (name1, name2)) ret |= KEY_NAME; if (size1 != size2) ret |= KEY_VALUE; else if (!value1 || !value2) ret |= KEY_VALUE; else if (memcmp (value1, value2, size1)) ret |= KEY_VALUE; // TODO: rewind metadata to previous position return ret; }
void test_owner() { Key *key; succeed_if (key = keyNew(0), "could not create new key"); succeed_if (keyValue(keyGetMeta(key, "owner")) == 0, "owner set for empty key"); succeed_if (!strcmp(keyOwner(key), ""), "owner set for empty key"); succeed_if (keyDel (key) == 0, "could not delete key"); succeed_if (key = keyNew("system/key", KEY_END), "could not create new key"); succeed_if (keyValue(keyGetMeta(key, "owner")) == 0, "owner set for empty key"); succeed_if (!strcmp(keyOwner(key), ""), "owner set for empty key"); succeed_if (keyDel (key) == 0, "could not delete key"); succeed_if (key = keyNew("user/key", KEY_END), "could not create new key"); succeed_if (keyValue(keyGetMeta(key, "owner")) == 0, "owner set for empty key"); succeed_if (!strcmp(keyOwner(key), ""), "owner set for empty key"); succeed_if (keyDel (key) == 0, "could not delete key"); succeed_if (key = keyNew("user/key", KEY_END), "could not create new key"); succeed_if (keySetOwner(key,"markus") == sizeof("markus"), "could not set owner markus"); succeed_if (!strcmp(keyValue(keyGetMeta(key, "owner")), "markus"), "no owner set for key"); succeed_if (!strcmp(keyOwner(key), "markus"), "no owner set for key"); succeed_if (keyDel (key) == 0, "could not delete key"); succeed_if (key = keyNew("user:markus/key", KEY_END), "could not create new key"); succeed_if (keySetOwner(key,"markus") == sizeof("markus"), "could not set owner markus"); succeed_if (!strcmp(keyValue(keyGetMeta(key, "owner")), "markus"), "no owner set for key"); succeed_if (!strcmp(keyOwner(key), "markus"), "no owner set for key"); succeed_if (keyDel (key) == 0, "could not delete key"); setenv ("USER", "markus", 1); succeed_if (key = keyNew("user/key", KEY_END), "could not create new key with env"); succeed_if (keyValue(keyGetMeta(key, "owner")) == 0, "owner set for empty key with env"); succeed_if (!strcmp(keyOwner(key), ""), "owner set for empty key with env"); succeed_if (keyDel (key) == 0, "could not delete key with env"); }