Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief Methods for Key value manipulation.
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : */
8 :
9 :
10 : #ifdef HAVE_KDBCONFIG_H
11 : #include "kdbconfig.h"
12 : #endif
13 :
14 : #ifdef HAVE_STDARG_H
15 : #include <stdarg.h>
16 : #endif
17 :
18 : #ifdef HAVE_STRING_H
19 : #include <string.h>
20 : #endif
21 :
22 : #ifdef HAVE_STDLIB_H
23 : #include <stdlib.h>
24 : #endif
25 :
26 : #if DEBUG && defined(HAVE_STDIO_H)
27 : #include <stdio.h>
28 : #endif
29 :
30 : #include "kdbprivate.h"
31 :
32 :
33 : /**
34 : * @defgroup keyvalue Value Manipulation Methods
35 : * @ingroup key
36 : * @brief Methods to do various operations on Key values.
37 : *
38 : * A key can contain a value in different format. The most
39 : * likely situation is, that the value is interpreted as
40 : * text. Use keyGetString() for that.
41 : * You can save any Unicode Symbols and Elektra will
42 : * take care that you get the same back, independent of
43 : * your current environment.
44 : *
45 : * In some situations this idea fails. When you need exactly
46 : * the same value back without any interpretation of the
47 : * characters, there is keySetBinary(). If you use that, its
48 : * very likely that your Configuration is not according
49 : * to the standard. Also for Numbers, Booleans and Date you
50 : * should use keyGetString(). To do so, you might use strtod()
51 : * strtol() and then atol() or atof() to convert back.
52 : *
53 : * To use them:
54 : * @code
55 : #include <kdb.h>
56 : * @endcode
57 : *
58 : *
59 : */
60 :
61 :
62 : /*******************************************
63 : * General value manipulation methods *
64 : *******************************************/
65 :
66 :
67 : /**
68 : * Return a pointer to the real internal @p key value.
69 : *
70 : * This is a much more efficient version of keyGetString()
71 : * keyGetBinary(), and you should use it if you are responsible enough to
72 : * not mess up things. You are not allowed to modify anything
73 : * in the returned string. If you need a copy of the Value, consider
74 : * to use keyGetString() or keyGetBinary() instead.
75 : *
76 : * @section string String Handling
77 : *
78 : * If @p key is string (keyIsString()), you may cast the returned as a
79 : * @c "char *" because you'll get a NULL terminated regular string.
80 : *
81 : * keyValue() returns "" in string mode when there is no value. The reason is
82 : * @code
83 : key=keyNew(0);
84 : keySetString(key,"");
85 : keyValue(key); // you would expect "" here
86 : keyDel(key);
87 : * @endcode
88 : *
89 : * @section binary Binary Data Handling
90 : *
91 : * If the data is binary, the size of the value must be determined by
92 : * keyGetValueSize(), any strlen() operations are not suitable to determine
93 : * the size.
94 : *
95 : * keyValue() returns 0 in binary mode when there is no value. The reason is
96 : * @code
97 : key=keyNew(0);
98 : keySetBinary(key, 0, 0);
99 : keyValue(key); // you would expect 0 here
100 :
101 : keySetBinary(key,"", 1);
102 : keyValue(key); // you would expect "" (a pointer to '\0') here
103 :
104 : int i=23;
105 : keySetBinary(key, (void*)&i, 4);
106 : (int*)keyValue(key); // you would expect a pointer to (int)23 here
107 : keyDel(key);
108 : * @endcode
109 : *
110 : * @note Note that the Key structure keeps its own size field that is calculated
111 : * by library internal calls, so to avoid inconsistencies, you
112 : * must never use the pointer returned by keyValue() method to set a new
113 : * value. Use keySetString() or keySetBinary() instead.
114 : *
115 : * @warning Binary keys will return a NULL pointer when there is no data in contrast
116 : * to keyName(), keyBaseName(), keyOwner() and keyComment(). For string value the
117 : * behaviour is the same.
118 : *
119 : * @par Example:
120 : * @code
121 : KDB *handle = kdbOpen();
122 : KeySet *ks=ksNew(0, KS_END);
123 : Key *current=0;
124 :
125 : kdbGetByName(handle,ks,"system/sw/my",KDB_O_SORT|KDB_O_RECURSIVE);
126 :
127 : ksRewind(ks);
128 : while (current=ksNext(ks)) {
129 : size_t size=0;
130 :
131 : if (keyIsBin(current)) {
132 : size=keyGetValueSize(current);
133 : printf("Key %s has a value of size %d bytes. Value: <BINARY>\nComment: %s",
134 : keyName(current),
135 : size,
136 : keyComment(current));
137 : } else {
138 : size=elektraStrLen((char *)keyValue(current));
139 : printf("Key %s has a value of size %d bytes. Value: %s\nComment: %s",
140 : keyName(current),
141 : size,
142 : (char *)keyValue(current),
143 : keyComment(current));
144 : }
145 : }
146 :
147 : ksDel (ks);
148 : kdbClose (handle);
149 : * @endcode
150 : *
151 : * @param key the key object to work with
152 : * @return a pointer to internal value
153 : * @retval "" when there is no data and key is not binary
154 : * @retval 0 where there is no data and key is binary
155 : * @retval 0 on NULL pointer
156 : * @see keyGetValueSize(), keyGetString(), keyGetBinary()
157 : * @ingroup keyvalue
158 : */
159 2036943 : const void * keyValue (const Key * key)
160 : {
161 2036943 : if (!key) return 0;
162 :
163 648382 : if (!key->data.v)
164 : {
165 : /*errno=KDB_ERR_NOKEY;*/
166 2535 : if (keyIsBinary (key))
167 : return 0;
168 : else
169 2437 : return "";
170 : }
171 :
172 : return key->data.v;
173 : }
174 :
175 :
176 : /**
177 : * Get the c-string representing the value.
178 : *
179 : * Will return (null) on null pointers.
180 : * Will return (binary) on binary data not ended
181 : * with a null byte.
182 : *
183 : * It is not checked if it is actually a string,
184 : * only if it terminates for security reasons.
185 : *
186 : * @return the c-string of the value
187 : * @retval "(null)" on null keys
188 : * @retval "" if no data found
189 : * @retval "(binary)" on binary keys
190 : * @ingroup keyvalue
191 : * @param key the key object to get the string from
192 : */
193 1512450 : const char * keyString (const Key * key)
194 : {
195 1512450 : if (!key) return "(null)";
196 :
197 1495785 : if (!key->data.c)
198 : {
199 : return "";
200 : }
201 :
202 1437598 : if (keyIsBinary (key))
203 : {
204 : return "(binary)";
205 : }
206 :
207 1437574 : return key->data.c;
208 : }
209 :
210 :
211 : /**
212 : * Returns the number of bytes needed to store the key value, including the
213 : * NULL terminator.
214 : *
215 : * It returns the correct size, independent of the Key Type.
216 : * If it is a binary there might be '\\0' values in it.
217 : *
218 : * For an empty string you need one byte to store the ending NULL.
219 : * For that reason 1 is returned. This is not true for binary data,
220 : * so there might be returned 0 too.
221 : *
222 : * A binary key has no '\\0' termination. String types have it, so to there
223 : * length will be added 1 to have enough space to store it.
224 : *
225 : * This method can be used with elektraMalloc() before keyGetString() or keyGetBinary()
226 : * is called.
227 : *
228 : * @code
229 : char *buffer;
230 : buffer = elektraMalloc (keyGetValueSize (key));
231 : // use this buffer to store the value (binary or string)
232 : // pass keyGetValueSize (key) for maxSize
233 : * @endcode
234 : *
235 : * @param key the key object to work with
236 : * @return the number of bytes needed to store the key value
237 : * @retval 1 when there is no data and type is not binary
238 : * @retval 0 when there is no data and type is binary
239 : * @retval -1 on null pointer
240 : * @see keyGetString(), keyGetBinary(), keyValue()
241 : * @ingroup keyvalue
242 : */
243 2163898 : ssize_t keyGetValueSize (const Key * key)
244 : {
245 2163898 : if (!key) return -1;
246 :
247 2163738 : if (!key->data.v)
248 : {
249 : /*errno=KDB_ERR_NODATA;*/
250 37705 : if (keyIsBinary (key))
251 : return 0;
252 : else
253 37355 : return 1;
254 : }
255 :
256 2126033 : return key->dataSize;
257 : }
258 :
259 :
260 : /**
261 : * Get the value of a key as a string.
262 : *
263 : * When there is no value inside the string, 1 will
264 : * be returned and the returnedString will be empty
265 : * "" to avoid programming errors that old strings are
266 : * shown to the user.
267 : *
268 : * For binary values see keyGetBinary() and keyIsBinary().
269 : *
270 : * @par Example:
271 : * @code
272 : Key *key = keyNew ("user/keyname", KEY_END);
273 : char buffer[300];
274 :
275 : if (keyGetString(key,buffer,sizeof(buffer)) == -1)
276 : {
277 : // handle error
278 : } else {
279 : printf ("buffer: %s\n", buffer);
280 : }
281 : * @endcode
282 : *
283 : * @param key the object to gather the value from
284 : * @param returnedString pre-allocated memory to store a copy of the key value
285 : * @param maxSize number of bytes of allocated memory in @p returnedString
286 : * @return the number of bytes actually copied to @p returnedString, including
287 : * final NULL
288 : * @retval 1 if the string is empty
289 : * @retval -1 on any NULL pointers
290 : * @retval -1 on type mismatch: string expected, but found binary
291 : * @retval -1 maxSize is 0
292 : * @retval -1 if maxSize is too small for string
293 : * @retval -1 if maxSize is larger than SSIZE_MAX
294 : * @see keyValue(), keyGetValueSize(), keySetString(), keyString()
295 : * @see keyGetBinary() for working with binary data
296 : * @ingroup keyvalue
297 : */
298 250365 : ssize_t keyGetString (const Key * key, char * returnedString, size_t maxSize)
299 : {
300 250365 : if (!key) return -1;
301 :
302 250363 : if (!maxSize) return -1;
303 250359 : if (!returnedString) return -1;
304 250357 : if (maxSize > SSIZE_MAX) return -1;
305 :
306 250355 : if (!keyIsString (key))
307 : {
308 : /*errno=KDB_ERR_TYPEMISMATCH;*/
309 : return -1;
310 : }
311 :
312 250332 : if (!key->data.v)
313 : {
314 32608 : returnedString[0] = 0;
315 32608 : return 1;
316 : }
317 :
318 217724 : if (key->dataSize > maxSize)
319 : {
320 : /*errno=KDB_ERR_TRUNC;*/
321 : return -1;
322 : }
323 :
324 :
325 217702 : strncpy (returnedString, key->data.c, maxSize);
326 217702 : return key->dataSize;
327 : }
328 :
329 :
330 : /**
331 : * Set the value for @p key as @p newStringValue.
332 : *
333 : * The function will allocate and save a private copy of @p newStringValue, so
334 : * the parameter can be freed after the call.
335 : *
336 : * String values will be saved in backend storage, when kdbSetKey() will be
337 : * called, in UTF-8 universal encoding, regardless of the program's current
338 : * encoding, when iconv plugin is present.
339 : *
340 : * @note The type will be set to KEY_TYPE_STRING.
341 : * When the type of the key is already a string type it won't be changed.
342 : *
343 : * @param key the key to set the string value
344 : * @param newStringValue NULL-terminated text string to be set as @p key's
345 : * value
346 : * @return the number of bytes actually saved in private struct including final
347 : * NULL
348 : * @retval 1 if newStringValue is a NULL pointer, this will make the
349 : * string empty (string only containing null termination)
350 : * @retval -1 if key is a NULL pointer
351 : * @see keyGetString(), keyValue(), keyString()
352 : * @ingroup keyvalue
353 : */
354 1478559 : ssize_t keySetString (Key * key, const char * newStringValue)
355 : {
356 1478559 : ssize_t ret = 0;
357 :
358 1478559 : if (!key) return -1;
359 :
360 1478494 : keySetMeta (key, "binary", 0);
361 :
362 1478494 : if (!newStringValue || newStringValue[0] == '\0')
363 278583 : ret = keySetRaw (key, 0, 0);
364 : else
365 1199911 : ret = keySetRaw (key, newStringValue, elektraStrLen (newStringValue));
366 :
367 1478494 : keySetMeta (key, "origvalue", 0);
368 :
369 1478494 : return ret;
370 : }
371 :
372 :
373 : /**
374 : * Get the value of a key as a binary.
375 : *
376 : * If the type is not binary -1 will be returned.
377 : *
378 : * When the binary data is empty (this is not the same as ""!)
379 : * 0 will be returned and the returnedBinary will not be changed.
380 : *
381 : * For string values see keyGetString() and keyIsString().
382 : *
383 : * When the returnedBinary is to small to hold the data
384 : * (its maximum size is given by maxSize),
385 : * the returnedBinary will not be changed and -1 is returned.
386 : *
387 : * @par Example:
388 : * @code
389 : Key *key = keyNew ("user/keyname", KEY_TYPE, KEY_TYPE_BINARY, KEY_END);
390 : char buffer[300];
391 :
392 : if (keyGetBinary(key,buffer,sizeof(buffer)) == -1)
393 : {
394 : // handle error
395 : }
396 : * @endcode
397 : *
398 : * @param key the object to gather the value from
399 : * @param returnedBinary pre-allocated memory to store a copy of the key value
400 : * @param maxSize number of bytes of pre-allocated memory in @p returnedBinary
401 : * @return the number of bytes actually copied to @p returnedBinary
402 : * @retval 0 if the binary is empty
403 : * @retval -1 on NULL pointers
404 : * @retval -1 if maxSize is 0
405 : * @retval -1 if maxSize is too small for string
406 : * @retval -1 if maxSize is larger than SSIZE_MAX
407 : * @retval -1 on type mismatch: binary expected, but found string
408 : * @see keyValue(), keyGetValueSize(), keySetBinary()
409 : * @see keyGetString() and keySetString() as preferred alternative to binary
410 : * @see keyIsBinary() to see how to check for binary type
411 : * @ingroup keyvalue
412 : */
413 91755 : ssize_t keyGetBinary (const Key * key, void * returnedBinary, size_t maxSize)
414 : {
415 91755 : if (!key) return -1;
416 91753 : if (!returnedBinary) return -1;
417 91751 : if (!maxSize) return -1;
418 :
419 91749 : if (maxSize > SSIZE_MAX) return -1;
420 :
421 91747 : if (!keyIsBinary (key))
422 : {
423 : /*errno=KDB_ERR_TYPEMISMATCH;*/
424 : return -1;
425 : }
426 :
427 91742 : if (!key->data.v)
428 : {
429 : return 0;
430 : }
431 :
432 91724 : if (key->dataSize > maxSize)
433 : {
434 : /*errno=KDB_ERR_TRUNC;*/
435 : return -1;
436 : }
437 :
438 91698 : memcpy (returnedBinary, key->data.v, key->dataSize);
439 91698 : return key->dataSize;
440 : }
441 :
442 :
443 : /**
444 : * Set the value of a key as a binary.
445 : *
446 : * A private copy of @p newBinary will allocated and saved inside @p key,
447 : * so the parameter can be deallocated after the call.
448 : *
449 : * Binary values might be encoded in another way then string values
450 : * depending on the plugin. Typically character encodings should not take
451 : * place on binary data.
452 : * Consider using a string key instead.
453 : *
454 : * When newBinary is a NULL pointer the binary will be freed and 0 will
455 : * be returned.
456 : *
457 : * @note The metadata "binary" will be set to mark that the key is
458 : * binary from now on. When the key is already binary the metadata
459 : * won't be changed. This will only happen in the successful case,
460 : * but not when -1 is returned.
461 : *
462 : * @param key the object on which to set the value
463 : * @param newBinary is a pointer to any binary data or NULL to free the previous set data
464 : * @param dataSize number of bytes to copy from @p newBinary
465 : * @return the number of bytes actually copied to internal struct storage
466 : * @retval 0 when the internal binary was freed and is now a null pointer
467 : * @retval -1 if key is a NULL pointer
468 : * @retval -1 when dataSize is 0 (but newBinary not NULL) or larger than SSIZE_MAX
469 : * @see keyGetBinary()
470 : * @see keyIsBinary() to check if the type is binary
471 : * @see keyGetString() and keySetString() as preferred alternative to binary
472 : * @ingroup keyvalue
473 : */
474 241879 : ssize_t keySetBinary (Key * key, const void * newBinary, size_t dataSize)
475 : {
476 241879 : ssize_t ret = 0;
477 :
478 241879 : if (!key) return -1;
479 :
480 241877 : if (!dataSize && newBinary) return -1;
481 241870 : if (dataSize > SSIZE_MAX) return -1;
482 241862 : if (key->flags & KEY_FLAG_RO_VALUE) return -1;
483 :
484 241854 : keySetMeta (key, "binary", "");
485 :
486 241854 : ret = keySetRaw (key, newBinary, dataSize);
487 :
488 :
489 241854 : return ret;
490 : }
491 :
492 : /**
493 : * @internal
494 : *
495 : * Set raw data as the value of a key.
496 : * If NULL pointers are passed, key value is cleaned.
497 : * This method will not change or set the key type, and should only
498 : * be used internally in elektra.
499 : *
500 : * @param key the key object to work with
501 : * @param newBinary array of bytes to set as the value
502 : * @param dataSize number bytes to use from newBinary, including the final NULL
503 : * @return The number of bytes actually set in internal buffer.
504 : * @retval 1 if it was a string which was deleted
505 : * @retval 0 if it was a binary which was deleted
506 : * @see keySetType(), keySetString(), keySetBinary()
507 : * @ingroup keyvalue
508 : */
509 1868500 : ssize_t keySetRaw (Key * key, const void * newBinary, size_t dataSize)
510 : {
511 1868500 : if (!key) return -1;
512 1868500 : if (key->flags & KEY_FLAG_RO_VALUE) return -1;
513 :
514 1868490 : if (!dataSize || !newBinary)
515 : {
516 278934 : if (key->data.v)
517 : {
518 61139 : if (!test_bit (key->flags, KEY_FLAG_MMAP_DATA)) elektraFree (key->data.v);
519 61139 : key->data.v = NULL;
520 61139 : clear_bit (key->flags, (keyflag_t) KEY_FLAG_MMAP_DATA);
521 : }
522 278934 : key->dataSize = 0;
523 278934 : set_bit (key->flags, KEY_FLAG_SYNC);
524 278934 : if (keyIsBinary (key)) return 0;
525 278586 : return 1;
526 : }
527 :
528 1589556 : key->dataSize = dataSize;
529 1589556 : if (key->data.v)
530 : {
531 324254 : char * previous = key->data.v;
532 :
533 324254 : if (test_bit (key->flags, KEY_FLAG_MMAP_DATA))
534 : {
535 8 : clear_bit (key->flags, (keyflag_t) KEY_FLAG_MMAP_DATA);
536 8 : key->data.v = elektraMalloc (key->dataSize);
537 8 : if (key->data.v == NULL) return -1;
538 : }
539 : else
540 : {
541 324246 : if (-1 == elektraRealloc ((void **) &key->data.v, key->dataSize)) return -1;
542 : }
543 :
544 324254 : if (-1 == elektraRealloc ((void **) &key->data.v, key->dataSize)) return -1;
545 324254 : if (previous == key->data.v)
546 : {
547 : // In case the regions overlap, use memmove to stay safe
548 187846 : memmove (key->data.v, newBinary, key->dataSize);
549 : }
550 : else
551 : {
552 136408 : memcpy (key->data.v, newBinary, key->dataSize);
553 : }
554 : }
555 : else
556 : {
557 1265302 : char * p = elektraMalloc (key->dataSize);
558 1265302 : if (NULL == p) return -1;
559 1265302 : key->data.v = p;
560 1265302 : memcpy (key->data.v, newBinary, key->dataSize);
561 : }
562 :
563 1589556 : set_bit (key->flags, KEY_FLAG_SYNC);
564 1589556 : return keyGetValueSize (key);
565 : }
|