1 /***************************************************************************
2 key.c - Methods for Key manipulation
4 begin : Mon Dec 29 2003
5 copyright : (C) 2003 by Avi Alkalay
7 ***************************************************************************/
9 /***************************************************************************
11 * This program is free software; you can redistribute it and/or modify *
12 * it under the terms of the BSD License (revised). *
14 ***************************************************************************/
18 * @defgroup key Key :: Basic Methods
19 * @brief Key construction and initialization methods.
26 * A Key is the essential class that encapsulates key @link keyname name @endlink,
27 * @link keyvalue value @endlink and @link keymeta metainfo @endlink.
29 * - @link keyname Key name @endlink
30 * - @link keyvalue Key value @endlink
31 * - @link keySetType() Data type @endlink
32 * - @link keyGetComment() Key comment @endlink
33 * - @link keyGetOwner() Key owner @endlink
34 * - @link keymeta UID, GID and filesystem-like mode permissions @endlink
35 * - @link keymeta Mode, change and modification times @endlink
37 * Described here the methods to allocate and free the key.
47 #if DEBUG && HAVE_STDIO_H
64 #include "kdbprivate.h"
68 * A practical way to fully create a Key object in one step.
70 * This function tries to mimic the C++ way for constructors.
72 * To just get a key object, simple do:
79 * If you want the key object to contain a name, value, comment and other
82 * @note When you already have a key with similar properties its
83 * easier and cheaper to keyDup() the key.
85 * Due to ABI compatibility, the @p Key structure is not defined in kdb.h,
86 * only declared. So you can only declare @p pointers to @p Keys in your
87 * program, and allocate and free memory for them with keyNew()
88 * and keyDel() respectively.
89 * See http://tldp.org/HOWTO/Program-Library-HOWTO/shared-libraries.html#AEN135
91 * You can call it in many different ways depending on the attribute tags you
92 * pass as parameters. Tags are represented as the #keyswitch_t values,
93 * and tell keyNew() which Key attribute comes next.
95 * The simplest and minimum way to use it is with no tags, only a key name:
97 Key *nullKey,*emptyNamedKey;
99 // Create a key that has no name, is completely empty, but is initialized
103 // Is the same as above
104 nullKey=keyNew("", KEY_END);
107 // Create and initialize a key with a name and nothing else
108 emptyNamedKey=keyNew("user/some/example",KEY_END);
109 keyDel (emptyNamedKey);
112 * keyNew() allocates memory for a key object and cleans everything up. After
113 * that, it processes the given argument list.
115 * The Key attribute tags are the following:
116 * - keyswitch_t::KEY_TYPE \n
117 * Next parameter is a type of the value. Default assumed is KEY_TYPE_UNDEFINED.
118 * Set this attribute so that a subsequent KEY_VALUE can toggle to keySetString()
119 * or keySetBinary() regarding to keyIsString() or keyIsBinary().
120 * If you don't use KEY_TYPE but a KEY_VALUE follows afterwards, KEY_TYPE_STRING
122 * - keyswitch_t::KEY_SIZE \n
123 * Define a maximum length of the value. This is especially useful for setting
124 * a binary key. So make sure you use that before you KEY_VALUE for
126 * - keyswitch_t::KEY_VALUE \n
127 * Next parameter is a pointer to the value that will be set to the key
128 * If no keyswitch_t::KEY_TYPE was used before,
129 * keyswitch_t::KEY_TYPE_STRING is assumed. If KEY_TYPE was previously
130 * passed with a KEY_TYPE_BINARY,
131 * you should have passed KEY_SIZE before! Otherwise it will be cut of
132 * with first \\0 in string!
133 * - keyswitch_t::KEY_UID, @p keyswitch_t::KEY_GID \n
134 * Next parameter is taken as the UID (uid_t) or GID (gid_t) that will
135 * be defined on the key. See keySetUID() and keySetGID().
136 * - keyswitch_t::KEY_MODE \n
137 * Next parameter is taken as mode permissions (mode_t) to the key.
139 * - keyswitch_t::KEY_DIR \n
140 * Define that the key is a directory rather than a ordinary key.
141 * This means its executable bits in its mode are set. This option
142 * allows the key to have subkeys.
144 * - keyswitch_t::KEY_OWNER \n
145 * Next parameter is the owner. See keySetOwner().
146 * - keyswitch_t::KEY_COMMENT \n
147 * Next parameter is a comment. See keySetComment().
148 * - keyswitch_t::KEY_REMOVE \n
149 * Mark the key to be removed instead of set it.
151 * - keyswitch_t::KEY_STAT \n
152 * Mark the key to be stated instead of get it.
154 * - keyswitch_t::KEY_END \n
155 * Must be the last parameter passed to keyNew(). It is always
156 * required, unless the @p keyName is 0.
162 ksAppendKey(ks,keyNew(0)); // an empty key
164 ksAppendKey(ks,keyNew("user/sw", // the name of the key
165 KEY_END)); // no more args
167 ksAppendKey(ks,keyNew("user/tmp/ex1",
168 KEY_VALUE,"some data", // set a string value
169 KEY_END)); // end of args
171 ksAppendKey(ks,keyNew("user/tmp/ex2",
172 KEY_VALUE,"some data", // with a simple value
173 KEY_MODE,0777, // permissions
174 KEY_END)); // end of args
176 ksAppendKey(ks,keyNew("user/tmp/ex4",
177 KEY_TYPE,KEY_TYPE_BINARY, // key type
178 KEY_SIZE,7, // assume binary length 7
179 KEY_VALUE,"some data", // value that will be truncated in 7 bytes
180 KEY_COMMENT,"value is truncated",
181 KEY_OWNER,"root", // owner (not uid) is root
182 KEY_UID,0, // root uid
183 KEY_END)); // end of args
185 ksAppendKey(ks,keyNew("user/tmp/ex5",
187 KEY_TYPE_DIR | KEY_TYPE_BINARY,// dir key with a binary value
189 KEY_VALUE,"some data", // value that will be truncated in 7 bytes
190 KEY_COMMENT,"value is truncated",
191 KEY_OWNER,"root", // owner (not uid) is root
192 KEY_UID,0, // root uid
193 KEY_END)); // end of args
198 * The reference counter (see keyGetRef()) will be initialized
199 * with 0, that means a subsequent call of keyDel() will delete
200 * the key. If you append the key to a keyset the reference counter
201 * will be incremented by one (see keyInc()) and the key can't be
202 * be deleted by a keyDel().
205 Key *k = keyNew(0); // ref counter 0
206 ksAppendKey(ks, k); // ref counter of key 1
207 ksDel(ks); // key will be deleted with keyset
210 * If you increment only by one with keyInc() the same as said above
214 Key *k = keyNew(0); // ref counter 0
215 keyIncRef(k); // ref counter of key 1
216 keyDel(k); // has no effect
217 keyDecRef(k); // ref counter back to 0
218 keyDel(k); // key is now deleted
221 * If you add the key to more keySets:
224 Key *k = keyNew(0); // ref counter 0
225 ksAppendKey(ks1, k); // ref counter of key 1
226 ksAppendKey(ks2, k); // ref counter of key 2
227 ksDel(ks1); // ref counter of key 1
228 ksDel(ks2); // k is now deleted
231 * or use keyInc() more than once:
234 Key *k = keyNew(0); // ref counter 0
235 keyIncRef(k); // ref counter of key 1
236 keyDel (k); // has no effect
237 keyIncRef(k); // ref counter of key 2
238 keyDel (k); // has no effect
239 keyDecRef(k); // ref counter of key 1
240 keyDel (k); // has no effect
241 keyDecRef(k); // ref counter is now 0
242 keyDel (k); // k is now deleted
245 * they key won't be deleted by a keyDel() as long refcounter is not 0.
247 * The key's sync bit will always be set for any call, except:
250 // keyNeedSync() will be false
253 * @param keyName a valid name to the key, or NULL to get a simple
254 * initialized, but really empty, object
256 * @return a pointer to a new allocated and initialized Key object,
257 * or NULL if an invalid @p keyName was passed (see keySetName()).
261 Key *keyNew(const char *keyName, ...) {
265 if (keyName) va_start(va,keyName);
266 k = keyVNew (keyName, va);
267 if (keyName) va_end (va);
273 Key *keyVNew (const char *keyName, va_list va)
277 keyswitch_t action=0;
279 ssize_t valueSize=-1;
281 key=(Key *)malloc(sizeof(Key));
286 keySetName(key,keyName);
288 action=va_arg(va, keyswitch_t);
292 type = (type_t) va_arg(va, type_t);
293 keySetType(key, type);
296 valueSize=va_arg(va, size_t);
299 value = va_arg(va, void *);
300 if (valueSize>=0 && keyIsBinary(key))
302 keySetBinary(key,value, valueSize);
303 } else if (keyIsBinary(key)) {
304 valueSize = (ssize_t) kdbiStrLen (value);
305 keySetBinary(key,value, valueSize);
307 keySetString(key,value);
311 keySetUID(key,va_arg(va,uid_t));
314 keySetGID(key,va_arg(va,gid_t));
317 keySetMode(key,va_arg(va, mode_t));
320 keySetOwner(key,va_arg(va,char *));
323 keySetComment(key,va_arg(va,char *));
336 fprintf (stderr, "Unknown option in keyNew %ld\n", (long int)action);
340 action=va_arg(va, keyswitch_t);
347 * Return a duplicate of a key.
349 * Memory will be allocated as needed for dynamic properties.
351 * The new key will not be member of any KeySet and
352 * will start with a new reference counter at 0. A
353 * subsequent keyDel() will delete the key.
356 int f (const Key * source)
358 Key * dup = keyDup (source);
359 // work with duplicate
361 // everything related to dup is freed
362 // and source is unchanged
366 * Like for a new key after keyNew() a subsequent ksAppend()
367 * makes a KeySet to take care of the lifecycle of the key.
370 int g (const Key * source, KeySet * ks)
372 Key * dup = keyDup (source);
373 // work with duplicate
374 ksAppendKey (ks, dup);
375 // ksDel(ks) will also free the duplicate
376 // source remains unchanged.
380 * Duplication of keys should be preferred to keyNew(),
381 * because data like owner can be filled with a copy
382 * of the key instead of asking the environment.
383 * It can also be optimized in the checks, because the keyname
384 * is known to be valid.
386 * @param source has to be an initializised source Key
387 * @return 0 failure or on NULL pointer
388 * @return a fully copy of source on success
389 * @see ksAppend(), keyDel()
390 * @see keyClear(), keyNew()
393 Key* keyDup(const Key *source)
397 if (!source) return 0;
399 dest = (Key *)malloc(sizeof(Key));
403 /* Copy the struct data, including the "next" pointer */
406 /* prepare to set dynamic properties */
412 dest->ksReference = 0;
414 if (source->key && keySetName(dest,source->key) == -1) goto memerror;
415 if (source->comment && keySetComment(dest,source->comment) == -1) goto memerror;
416 if (source->owner && keySetOwner(dest,source->owner) == -1) goto memerror;
417 if (source->data && keySetRaw(dest,source->data,source->dataSize) == -1) goto memerror;
429 * Copy or Clear a key.
431 * Most often you may prefer keyDup() which allocates
432 * a new key and returns a duplication of another key.
434 * But when you need to copy into an existing key, e.g.
435 * because it was passed by a pointer in a function
443 // the caller will see the changed key k
447 * The reference counter will not change for
448 * the destination key. Affiliation to keysets
449 * are also not affected.
451 * When you pass a NULL-pointer as source the
452 * data of dest will be cleaned completely and
453 * you get a fresh dest key.
459 // k is now an empty and fresh key
463 * @param dest the key which will be written to
464 * @param source the key which should be copied
465 * or NULL to clean the destination key
467 * @return -1 on failure when a NULL pointer
468 * was passed for dest or a dynamic property could not
470 * @return 0 when dest was cleaned
471 * @return 1 when source was successfully copied
472 * @see keyDup() to get a duplication of a key
474 int keyCopy (Key *dest, const Key *source)
478 if (!dest) return -1;
479 destref = dest->ksReference;
481 /* free everything in dest */
482 keySetName (dest, 0);
483 keySetComment (dest,0);
484 keySetOwner (dest, 0);
485 keySetRaw (dest, 0, 0);
489 if (!source) return 0;
491 /* copy all data of structure */
494 /* Set reference properties */
495 dest->ksReference = destref;
497 /* prepare to set dynamic properties */
503 if (keySetName(dest,source->key) == -1) return -1;
504 if (keySetComment(dest,source->comment) == -1) return -1;
505 if (keySetOwner(dest,source->owner) == -1) return -1;
506 if (keySetRaw(dest,source->data,source->dataSize) == -1) return -1;
516 * A destructor for Key objects.
518 * Every key created by keyNew() must be
519 * deleted with keyDel().
521 * It is save to delete keys which are
522 * in a keyset, the number of references
523 * will be returned then.
525 * It is save to delete a nullpointer,
526 * -1 will be returned then.
528 * @param key the key object to delete
529 * @see keyNew(), keyInc(), keyGetRef()
530 * @return the value of the reference counter
531 * if the key is within keyset(s)
532 * @return 0 when the key was freed
533 * @return -1 on null pointers
537 int keyDel(Key *key) {
542 if (key->ksReference > 0)
544 return key->ksReference;
554 * Key Object Cleaner.
556 * Will reset all internal data.
558 * After this call you will receive a fresh
565 // you have a fresh key k here
566 keySetString (k, "value");
567 // the caller will get an empty key k with an value
571 * @param key the key object to work with
574 int keyClear(Key *key)
576 if (key->key) free(key->key);
577 if (key->data) free(key->data);
578 if (key->comment) free(key->comment);
579 if (key->owner) free(key->owner);
581 memset(key,0,sizeof(Key));
590 * Increment the viability of a key object.
592 * This function is intended for applications
593 * using their own reference counter for
594 * key objects. With it you can increment
595 * the reference and thus avoid destruction
596 * of the object in a subsequent keyDel().
601 function_that_keyDec(k);
603 keyDel (k); // now really free it
606 * The reference counter can't be incremented
607 * once it reached SSIZE_MAX. In that situation
608 * nothing will happen and SSIZE_MAX will be
611 * @return the value of the new reference counter
612 * @return -1 on null pointer
613 * @return SSIZE_MAX when maximum exceeded
614 * @param key the key object to work with
615 * @see keyGetRef(), keyDecRef(), keyDel()
618 ssize_t keyIncRef(Key *key)
622 if (key->ksReference < SSIZE_MAX) return ++ key->ksReference;
623 else return SSIZE_MAX;
629 * Decrement the viability of a key object.
631 * The reference counter can't be decremented
632 * once it reached 0. In that situation
633 * nothing will happen and 0 will be
636 * @return the value of the new reference counter
637 * @return -1 on null pointer
638 * @return 0 when the key is ready to be freed
639 * @param key the key object to work with
640 * @see keyGetRef(), keyDel(), keyIncRef()
643 ssize_t keyDecRef(Key *key)
647 if (key->ksReference>0) return -- key->ksReference;
655 * Return how many references the key has.
657 * The references will be incremented when ksAppendKey()
658 * or ksAppend() uses the key and will be decremented when
661 * keyDup() will reset the references for dupped
664 * For your own applications you can use
665 * keyIncRef() and keyDelRef() for reference
666 * counting. Keys with zero references
667 * will be deleted when using keyDel().
669 * @param key the key object to work with
670 * @return the number of references
671 * @return -1 on null pointer
672 * @see keyIncRef() and keyDecRef()
675 ssize_t keyGetRef(const Key *key)
679 return key->ksReference;