Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief Methods for Key name manipulation.
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : */
8 :
9 : /** @class doxygenNamespaces
10 : *
11 : * @brief .
12 : *
13 : * .
14 : *
15 : * - @p spec/something for specification of other keys.
16 : * - @p proc/something for in-memory keys, e.g. commandline.
17 : * - @p dir/something for dir keys in current working directory
18 : * - @p system/something for system keys in /etc or /
19 : * - @p user/something for user keys in home directory
20 : * - @p user:username/something for other users (deprecated: kdbGet() + kdbSet() currently unsupported)
21 : * - @p /something for cascading keys (actually refers to one of the above, see also ksLookup())
22 : *
23 : */
24 :
25 :
26 : /**
27 : * @defgroup keyname Name Manipulation Methods
28 : * @ingroup key
29 : * @brief Methods to do various operations on Key names.
30 : *
31 : * To use them:
32 : * @code
33 : #include <kdb.h>
34 : * @endcode
35 : *
36 : * These functions make it easier for C programmers to work with key names.
37 : *
38 : *
39 : * @par Terminology of Key Names
40 : * - A *key name* (see keySetName() and keyName()) defines the
41 : * place of a key within the key database.
42 : * To be unique, it is always absolute and canonical.
43 : * - Key names are composed out of many *key name parts* split by a
44 : * separator. These *key name parts* do not contain an unescaped
45 : * separator.
46 : * - A *key base name* (see keySetBaseName() and keyAddBaseName()) is
47 : * the last part of the key name.
48 : * - A *C-String* is a null terminated sequence of characters.
49 : * So \\0 (null-character) must not occur within a C-String.
50 : *
51 : * @par Namespaces
52 : * A namespace denotes the place the key comes from:
53 : *
54 : * @copydetails doxygenNamespaces
55 : *
56 : *
57 : * @note The rules are currently not formally specified and are subject
58 : * of change in the next major release.
59 : * So, always prefer:
60 : * - To use keySetName() and keyAddName() to get the canonified version of the keyname
61 : * - To use keySetBaseName() and keyAddBaseName() to get an escaped key
62 : * name part.
63 : * - Not to escape or canonify with your own algorithms!
64 : * - To use keyUnescapedName() and keyBaseName() to have access to the
65 : * key name without escape sequences (key name parts are null
66 : * terminated)
67 : * - Not to unescape the strings yourself!
68 : *
69 : *
70 : * @par Syntax for Key Names
71 : * Key names and key name parts have following goals:
72 : * - The C-String passed to keySetName() and keyAddName() may be any
73 : * C-String.
74 : * - The *key name parts* (e.g. keySetBaseName(), keyBaseName()) may
75 : * be any C-String.
76 : * Escaping is needed to achieve both goals.
77 : *
78 : *
79 : * @par Semantics for Key Name Parts
80 : * - \% denotes an empty key name part.
81 : *
82 : *
83 : * @par Canonicalization for Key Names
84 : * - / (slash) is the separator between key name parts.
85 : * - // is shortened to /
86 : * - trailing / (slashes) are removed
87 : * - . (dot) and .. (dot-dot) is removed in an canonical key name, with
88 : * following rules:
89 : * - /./ is shortened to /
90 : * - _/../ is shortened to _
91 : *
92 : *
93 : * @par Conventions for key names
94 : * - Key name parts starting with \# are array elements.
95 : * Then only _ (underscore) followed by 0-9 is allowed.
96 : * So we have the regular expression #[_]*[0-9]+ with the further
97 : * limitation that the number of _ is defined by the number of
98 : * digits-1.
99 : * - Key name parts starting with _ are reserved for special purposes
100 : * (if you use this within a plugin you still have to make sure _ is
101 : * escaped properly)
102 : * - Key name parts starting with @ are reserved for special purposes
103 : * (if you use this within a plugin you still have to make sure @ is
104 : * escaped properly)
105 : * - If any key name part starts with . (dot) it means the key is
106 : * inactive, see keyIsInactive().
107 : *
108 : *
109 : * @par Escaping rules
110 : * - \\ (backslash) is the escape character for the situations as
111 : * described here (and only these).
112 : * The \\ character must only be escaped, when one of the following
113 : * rules apply.
114 : * - Stray escape characters are only possible in the end of the string.
115 : * - \\/ allows one to escape / (any uneven number of \\).
116 : * Does not introduce a new part.
117 : * - Any uneven number N of \\ before / allows you to escape / with the
118 : * N/2 of \\ prefixed.
119 : * Does not introduce a new part.
120 : * - \\\\/ allows one to use \\ as character before / and introduces a new
121 : * part.
122 : * - Any even number N of \\ before / allows you to have N/2 of \\
123 : * prefixed before a / which introduces a new part.
124 : * - Use \\. and \\.. if you want your key name part to represent . and ..
125 : * - \\\\. and \\\\.. allows us to use \\ as character before . and .. (and so on)
126 : * - Use \\% if you want your key name part to start with \% (and does
127 : * not represent an empty name)
128 : * - Using \\\\% allows one to use \\ as character before \% (and so on)
129 :
130 : *
131 : *
132 : * @par Semantics for Key Name Specifications
133 : * - _ denotes that the key name part is
134 : * arbitrary (syntax as described above).
135 : * - \# denotes that the key name part
136 : * has array syntax.
137 : * - names surrounded by \% (e.g. \%profile\%)
138 : * denotes a placeholder.
139 : *
140 : *
141 : * @{
142 : */
143 :
144 :
145 : #ifdef HAVE_KDBCONFIG_H
146 : #include "kdbconfig.h"
147 : #endif
148 :
149 : #include <kdbassert.h>
150 :
151 : #ifdef HAVE_STDARG_H
152 : #include <stdarg.h>
153 : #endif
154 :
155 : #ifdef HAVE_STRING_H
156 : #include <string.h>
157 : #endif
158 :
159 : #ifdef HAVE_STDLIB_H
160 : #include <stdlib.h>
161 : #endif
162 :
163 : #include "kdb.h"
164 : #include "kdbhelper.h"
165 : #include "kdbinternal.h"
166 :
167 :
168 : /*******************************************
169 : * General name manipulation methods *
170 : *******************************************/
171 :
172 :
173 : /**
174 : * Returns a pointer to the abbreviated real internal @p key name.
175 : *
176 : * This is a much more efficient version of keyGetName() and can use
177 : * it if you are responsible enough to not mess up things. You are not allowed
178 : * to change anything in the returned array. The content of that string
179 : * may change after keySetName() and similar functions. If you need a copy of the name,
180 : * consider using keyGetName().
181 : *
182 : * The name will be without owner, see keyGetFullName() if
183 : * you need the name with its owner.
184 : *
185 : * @retval "" when there is no keyName. The reason is
186 : * @code
187 : key=keyNew(0);
188 : keySetName(key,"");
189 : keyName(key); // you would expect "" here
190 : keyDel(key);
191 : * @endcode
192 : *
193 : * Valid key names are:
194 : *
195 : * @copydetails doxygenNamespaces
196 : *
197 : * @note Note that the Key structure keeps its own size field that is calculated
198 : * by library internal calls, so to avoid inconsistencies, you
199 : * must never use the pointer returned by keyName() method to set a new
200 : * value. Use keySetName() instead.
201 : *
202 : * @param key the key object to work with
203 : * @return a pointer to the keyname which must not be changed.
204 : * @retval "" when there is no (an empty) keyname
205 : * @retval 0 on NULL pointer
206 : * @see keyGetNameSize() for the string length
207 : * @see keyGetFullName(), keyGetFullNameSize() to get the full name
208 : * @see keyGetName() as alternative to get a copy
209 : * @see keyOwner() to get a pointer to owner
210 : * @see keyUnescapedName to get an unescaped key name
211 : * @ingroup keyname
212 : */
213 5998850 : const char * keyName (const Key * key)
214 : {
215 5998850 : if (!key) return 0;
216 :
217 5998741 : if (!key->key)
218 : {
219 : return "";
220 : }
221 :
222 5967772 : return key->key;
223 : }
224 :
225 : /**
226 : * Bytes needed to store the key name without owner.
227 : *
228 : * For an empty key name you need one byte to store the ending NULL.
229 : * For that reason 1 is returned.
230 : *
231 : * @param key the key object to work with
232 : * @return number of bytes needed, including ending NULL, to store key name
233 : * without owner
234 : * @retval 1 if there is is no key Name
235 : * @retval -1 on NULL pointer
236 : * @see keyGetName(), keyGetFullNameSize()
237 : * @see keyGetUnescapedNameSize to get size of unescaped name
238 : * @ingroup keyname
239 : */
240 846126 : ssize_t keyGetNameSize (const Key * key)
241 : {
242 846126 : if (!key) return -1;
243 :
244 759249 : if (!key->key)
245 : {
246 : return 1;
247 : }
248 : else
249 759175 : return key->keySize;
250 : }
251 :
252 :
253 : /**
254 : * @brief Returns a keyname which is null separated and does not use backslash for escaping
255 : *
256 : * Slashes are replaced with null bytes.
257 : * So cascading keys start with a null byte.
258 : * Otherwise escaped characters, e.g. non-hierarchy slash, will be unescaped.
259 : *
260 : * This name is essential if you want to iterate over parts of the key
261 : * name, want to compare keynames and want to check relations of keys in
262 : * the hierarchy.
263 : *
264 : * @param key the object to work with
265 : *
266 : * @see keyGetUnescapedNameSize()
267 : * @see keyName() for escaped variant
268 : * @retval 0 on null pointers
269 : * @retval "" if no name
270 : * @return the name in its unescaped form
271 : */
272 7317912 : const void * keyUnescapedName (const Key * key)
273 : {
274 7317912 : if (!key) return 0;
275 :
276 7317912 : if (!key->key)
277 : {
278 : return "";
279 : }
280 :
281 7317830 : return key->key + key->keySize;
282 : }
283 :
284 :
285 : /**
286 : * @brief return size of unescaped name with embedded and terminating null characters
287 : *
288 : * @param key the object to work with
289 : *
290 : * @see keyUnescapedName()
291 : * @see keyGetNameSize() for size of escaped variant
292 : * @retval -1 on null pointer
293 : * @retval 0 if no name
294 : */
295 8002622 : ssize_t keyGetUnescapedNameSize (const Key * key)
296 : {
297 8002622 : if (!key) return -1;
298 :
299 8002622 : if (!key->key)
300 : {
301 : return 0;
302 : }
303 : else
304 8002540 : return key->keyUSize;
305 : }
306 :
307 :
308 : /**
309 : * Get abbreviated key name (without owner name).
310 : *
311 : * When there is not enough space to write the name,
312 : * nothing will be written and -1 will be returned.
313 : *
314 : * maxSize is limited to SSIZE_MAX. When this value
315 : * is exceeded -1 will be returned. The reason for that
316 : * is that any value higher is just a negative return
317 : * value passed by accident. Of course elektraMalloc is not
318 : * as failure tolerant and will try to allocate.
319 : *
320 : * @code
321 : char *getBack = elektraMalloc (keyGetNameSize(key));
322 : keyGetName(key, getBack, keyGetNameSize(key));
323 : * @endcode
324 : *
325 : * @return number of bytes written to @p returnedName
326 : * @retval 1 when only a null was written
327 : * @retval -1 when keyname is longer then maxSize or 0 or any NULL pointer
328 : * @param key the key object to work with
329 : * @param returnedName pre-allocated memory to write the key name
330 : * @param maxSize maximum number of bytes that will fit in returnedName, including the final NULL
331 : * @see keyGetNameSize(), keyGetFullName(), keyGetFullNameSize()
332 : * @ingroup keyname
333 : */
334 5209 : ssize_t keyGetName (const Key * key, char * returnedName, size_t maxSize)
335 : {
336 5209 : if (!key) return -1;
337 :
338 5207 : if (!returnedName) return -1;
339 :
340 5205 : if (!maxSize) return -1;
341 :
342 5201 : if (maxSize > SSIZE_MAX) return -1;
343 :
344 5199 : if (!key->key)
345 : {
346 : /*errno=KDB_ERR_NOKEY;*/
347 4 : returnedName[0] = 0;
348 4 : return 1;
349 : }
350 :
351 5195 : if (key->keySize > maxSize)
352 : {
353 : /*errno=KDB_ERR_TRUNC;*/
354 : return -1;
355 : }
356 :
357 5177 : strncpy (returnedName, key->key, maxSize);
358 :
359 5177 : return key->keySize;
360 : }
361 :
362 : /**
363 : * @internal
364 : *
365 : * @brief Call this function after every key name changing operation
366 : *
367 : * @pre key->key and key->keySize are set accordingly and the size of
368 : * allocation is twice as what you actually needed.
369 : *
370 : * @post we get a unsynced key with a correctly terminated
371 : * key name suitable for ordering and the name getter methods
372 : *
373 : * It will duplicate the key length and put a second name afterwards
374 : * that is used for sorting keys.
375 : *
376 : * @param key
377 : */
378 14421331 : ssize_t elektraFinalizeName (Key * key)
379 : {
380 14421331 : key->key[key->keySize - 1] = 0; /* finalize string */
381 :
382 14421331 : key->keyUSize = elektraUnescapeKeyName (key->key, key->key + key->keySize);
383 :
384 14421331 : key->flags |= KEY_FLAG_SYNC;
385 :
386 14421331 : return key->keySize;
387 : }
388 :
389 178990 : ssize_t elektraFinalizeEmptyName (Key * key)
390 : {
391 178990 : key->key = elektraCalloc (2); // two null pointers
392 178990 : key->keySize = 1;
393 178990 : key->keyUSize = 1;
394 178990 : key->flags |= KEY_FLAG_SYNC;
395 :
396 178990 : return key->keySize;
397 : }
398 :
399 525921 : static void elektraHandleUserName (Key * key, const char * newName)
400 : {
401 525921 : const size_t userLength = sizeof ("user");
402 525921 : key->keyUSize = key->keySize = userLength;
403 :
404 525921 : const char delim = newName[userLength - 1];
405 : // no owner, we are finished
406 525921 : if (delim == '/' || delim == '\0') return;
407 1942 : ELEKTRA_ASSERT (delim == ':', "delimiter in user-name not `:' but `%c'", delim);
408 :
409 : // handle owner (compatibility, to be removed)
410 1942 : keyNameGetOneLevel (newName, &key->keyUSize);
411 1942 : const size_t ownerLength = key->keyUSize - userLength;
412 1942 : ++key->keyUSize;
413 1942 : char * owner = elektraMalloc (ownerLength + 1);
414 1942 : if (!owner) return; // out of memory, ok for owner
415 1942 : strncpy (owner, newName + userLength, ownerLength);
416 1942 : owner[ownerLength] = 0;
417 1942 : keySetOwner (key, owner);
418 1942 : elektraFree (owner);
419 : }
420 :
421 9754701 : static void elektraRemoveKeyName (Key * key)
422 : {
423 9754701 : if (key->key && !test_bit (key->flags, KEY_FLAG_MMAP_KEY)) elektraFree (key->key);
424 9754701 : clear_bit (key->flags, (keyflag_t) KEY_FLAG_MMAP_KEY);
425 9754701 : key->key = 0;
426 9754701 : key->keySize = 0;
427 9754701 : key->keyUSize = 0;
428 9754701 : }
429 :
430 : /**
431 : * @brief Checks if in name is something else other than slashes
432 : *
433 : * @param name the name to check
434 : *
435 : * @retval 0 if not only slashes
436 : * @retval 1 if only slashes
437 : */
438 : static int elektraOnlySlashes (const char * name)
439 : {
440 6007532 : size_t nameLen = strlen (name);
441 12018878 : for (size_t i = 0; i < nameLen; ++i)
442 : {
443 12015427 : if (name[i] != '/') return 0; // not only slashes
444 : }
445 : return 1; // only slashes
446 : }
447 :
448 :
449 : /**
450 : * @internal
451 : */
452 11638076 : static int keyGetNameNamespace (const char * name)
453 : {
454 11638076 : if (!name) return KEY_NS_EMPTY;
455 11621348 : if (!strcmp (name, "")) return KEY_NS_EMPTY;
456 11316006 : if (name[0] == '/')
457 : return KEY_NS_CASCADING;
458 10686327 : else if (keyNameIsSpec (name))
459 : return KEY_NS_SPEC;
460 10514812 : else if (keyNameIsProc (name))
461 : return KEY_NS_PROC;
462 10510002 : else if (keyNameIsDir (name))
463 : return KEY_NS_DIR;
464 10366160 : else if (keyNameIsUser (name))
465 : return KEY_NS_USER;
466 9297149 : else if (keyNameIsSystem (name))
467 : return KEY_NS_SYSTEM;
468 6154833 : return KEY_NS_META;
469 : }
470 :
471 :
472 : /**
473 : * Set a new name to a key.
474 : *
475 : * A valid name is one of the forms:
476 : * @copydetails doxygenNamespaces
477 : *
478 : * An invalid name either has an invalid namespace or
479 : * a wrongly escaped \\ at the end of the name.
480 : *
481 : * See @link keyname key names @endlink for the exact rules.
482 : *
483 : * The last form has explicitly set the owner, to let the library
484 : * know in which user folder to save the key. A owner is a user name.
485 : * If it is not defined (the second form) current user is used.
486 : *
487 : * You should always follow the guidelines for key tree structure creation.
488 : *
489 : * A private copy of the key name will be stored, and the @p newName
490 : * parameter can be freed after this call.
491 : *
492 : * .., . and / will be handled as in filesystem paths. A valid name will be build
493 : * out of the (valid) name what you pass, e.g. user///sw/../sw//././MyApp -> user/sw/MyApp
494 : *
495 : * On invalid names, NULL or "" the name will be "" afterwards.
496 : *
497 : *
498 : * @retval size in bytes of this new key name including ending NULL
499 : * @retval 0 if newName is an empty string or a NULL pointer (name will be empty afterwards)
500 : * @retval -1 if newName is invalid (name will be empty afterwards)
501 : * @retval -1 if key was inserted to a keyset before
502 : * @param key the key object to work with
503 : * @param newName the new key name
504 : * @see keyNew(), keySetOwner()
505 : * @see keyGetName(), keyGetFullName(), keyName()
506 : * @see keySetBaseName(), keyAddBaseName() to manipulate a name
507 : * @ingroup keyname
508 : */
509 736416 : ssize_t keySetName (Key * key, const char * newName)
510 : {
511 736416 : return elektraKeySetName (key, newName, 0);
512 : }
513 :
514 9755325 : ssize_t elektraKeySetName (Key * key, const char * newName, option_t options)
515 : {
516 9755325 : if (!key) return -1;
517 9754738 : if (test_bit (key->flags, KEY_FLAG_RO_NAME)) return -1;
518 :
519 9754695 : elektraRemoveKeyName (key);
520 9754695 : if (!(options & KEY_META_NAME)) keySetOwner (key, NULL);
521 :
522 9754695 : switch (keyGetNameNamespace (newName))
523 : {
524 : case KEY_NS_NONE:
525 0 : ELEKTRA_ASSERT (0, "non empty key has no namespace?");
526 : case KEY_NS_EMPTY:
527 178990 : elektraFinalizeEmptyName (key);
528 178990 : return 0; // as documented
529 : case KEY_NS_CASCADING:
530 592118 : key->keyUSize = 1;
531 592118 : key->keySize = sizeof ("/");
532 592118 : break;
533 : case KEY_NS_SPEC:
534 107474 : key->keyUSize = key->keySize = sizeof ("spec");
535 107474 : break;
536 : case KEY_NS_PROC:
537 3578 : key->keyUSize = key->keySize = sizeof ("proc");
538 3578 : break;
539 : case KEY_NS_DIR:
540 89388 : key->keyUSize = key->keySize = sizeof ("dir");
541 89388 : break;
542 : case KEY_NS_USER:
543 525921 : elektraHandleUserName (key, newName);
544 525921 : break;
545 : case KEY_NS_SYSTEM:
546 2103491 : key->keyUSize = key->keySize = sizeof ("system");
547 2103491 : break;
548 : case KEY_NS_META:
549 6153735 : if (!(options & KEY_META_NAME)) return -1;
550 6153619 : keyNameGetOneLevel (newName, &key->keySize);
551 6153619 : key->keyUSize = ++key->keySize; // for null
552 6153619 : break;
553 : } // Note that we abused keyUSize for cascading and user:owner
554 :
555 9575589 : const size_t length = elektraStrLen (newName);
556 9575589 : key->key = elektraMalloc (key->keySize * 2);
557 9575589 : memcpy (key->key, newName, key->keySize);
558 9575589 : if (length == key->keyUSize || length == key->keySize)
559 : { // use || because full length is keyUSize in user, but keySize for /
560 : // newName consisted of root only
561 3568057 : elektraFinalizeName (key);
562 3568057 : return key->keyUSize;
563 : }
564 :
565 12015064 : if (elektraOnlySlashes (newName + key->keyUSize - 1))
566 : {
567 3451 : elektraFinalizeName (key);
568 3451 : return key->keySize;
569 : }
570 :
571 6004081 : key->key[key->keySize - 1] = '\0';
572 6004081 : const ssize_t ret = keyAddName (key, newName + key->keyUSize);
573 6004081 : if (ret == -1)
574 6 : elektraRemoveKeyName (key);
575 : else
576 6004075 : return key->keySize;
577 6 : return ret;
578 : }
579 :
580 :
581 : /**
582 : * Bytes needed to store the key name including user domain and ending NULL.
583 : *
584 : * @param key the key object to work with
585 : * @return number of bytes needed to store key name including user domain
586 : * @retval 1 on empty name
587 : * @retval -1 on NULL pointer
588 : * @see keyGetFullName(), keyGetNameSize()
589 : * @ingroup keyname
590 : */
591 9125 : ssize_t keyGetFullNameSize (const Key * key)
592 : {
593 9125 : size_t returnedSize = 0;
594 :
595 9125 : if (!key) return -1;
596 :
597 9125 : if (!key->key) return 1;
598 :
599 9123 : returnedSize = elektraStrLen (key->key);
600 :
601 9123 : if (keyNameIsUser (key->key) && keyGetMeta (key, "owner")) returnedSize += keyGetOwnerSize (key);
602 :
603 : /*
604 : After 2 elektraStrLen() calls looks like we counted one more NULL.
605 : But we need this byte count because a full key name has an
606 : additional ':' char.
607 : */
608 :
609 9123 : return returnedSize;
610 : }
611 :
612 :
613 : /**
614 : * Get key full name, including the user domain name.
615 : *
616 : * @return number of bytes written
617 : * @retval 1 on empty name
618 : * @retval -1 on NULL pointers
619 : * @retval -1 if maxSize is 0 or larger than SSIZE_MAX
620 : * @param key the key object
621 : * @param returnedName pre-allocated memory to write the key name
622 : * @param maxSize maximum number of bytes that will fit in returnedName, including the final NULL
623 : * @ingroup keyname
624 : */
625 4463 : ssize_t keyGetFullName (const Key * key, char * returnedName, size_t maxSize)
626 : {
627 4463 : size_t userSize = sizeof ("user") - 1;
628 : ssize_t length;
629 : ssize_t maxSSize;
630 : char * cursor;
631 :
632 4463 : if (!key) return -1;
633 4461 : if (!returnedName) return -1;
634 4459 : if (!maxSize) return -1;
635 :
636 4455 : if (maxSize > SSIZE_MAX) return -1;
637 4453 : maxSSize = maxSize;
638 :
639 4453 : length = keyGetFullNameSize (key);
640 4453 : if (length == 1)
641 : {
642 : /*errno=KDB_ERR_NOKEY;*/
643 2 : returnedName[0] = 0;
644 2 : return length;
645 : }
646 4451 : else if (length < 0)
647 : return length;
648 4451 : else if (length > maxSSize)
649 : {
650 : /* errno=KDB_ERR_TRUNC; */
651 : return -1;
652 : }
653 :
654 4425 : cursor = returnedName;
655 4425 : if (keyIsUser (key))
656 : {
657 1769 : strncpy (cursor, key->key, userSize);
658 1769 : cursor += userSize;
659 1769 : if (keyGetMeta (key, "owner"))
660 : {
661 40 : *cursor = ':';
662 40 : ++cursor;
663 40 : size_t ownerSize = keyGetValueSize (keyGetMeta (key, "owner")) - 1;
664 40 : strncpy (cursor, keyValue (keyGetMeta (key, "owner")), ownerSize);
665 40 : cursor += ownerSize;
666 : }
667 1769 : strcpy (cursor, key->key + userSize);
668 : }
669 : else
670 2656 : strcpy (cursor, key->key);
671 :
672 : return length;
673 : }
674 :
675 :
676 : /**
677 : * @brief Returns a pointer to the internal unescaped key name where the @p basename starts.
678 : *
679 : * This is a much more efficient version of keyGetBaseName() and you should
680 : * use it if you are responsible enough to not mess up things. The name might
681 : * change or even point to a wrong place after a keySetName(). So make
682 : * sure to copy the memory before the name changes.
683 : *
684 : * keyBaseName() returns "" when there is no keyBaseName. The reason is
685 : * @snippet testabi_key.c base0 empty
686 : *
687 : * And there is also support for really empty basenames:
688 : * @snippet testabi_key.c base1 empty
689 : *
690 : * @note You must never use the pointer returned by keyBaseName()
691 : * method to change the name, but you should use keySetBaseName()
692 : * instead.
693 : *
694 : * @note Do not assume that keyBaseName() points to the same region as
695 : * keyName() does.
696 : *
697 : * @param key the object to obtain the basename from
698 : * @return a pointer to the basename
699 : * @retval "" when the key has no (base)name
700 : * @retval 0 on NULL pointer
701 : * @see keyGetBaseName(), keyGetBaseNameSize()
702 : * @see keyName() to get a pointer to the name
703 : * @see keyOwner() to get a pointer to the owner
704 : * @ingroup keyname
705 : */
706 1448252 : const char * keyBaseName (const Key * key)
707 : {
708 1448252 : if (!key) return 0;
709 1448244 : if (!key->key) return "";
710 :
711 1448237 : char * p = key->key + key->keySize + key->keyUSize - 1;
712 :
713 1448237 : char * base = p;
714 1448237 : while (*(--p))
715 : {
716 : base = p;
717 : }
718 :
719 1448237 : if (base != (key->key + key->keyUSize))
720 : return base;
721 : else
722 842 : return "";
723 : }
724 :
725 :
726 : /**
727 : * Calculates number of bytes needed to store basename of @p key.
728 : *
729 : * Key names that have only root names (e.g. @c "system" or @c "user"
730 : * or @c "user:domain" ) does not have basenames, thus the function will
731 : * return 1 bytes to store "".
732 : *
733 : * Basenames are denoted as:
734 : * - @c system/some/thing/basename -> @c basename
735 : * - @c user:domain/some/thing/base\\/name > @c base\\/name
736 : *
737 : * @param key the key object to work with
738 : * @return size in bytes of @p key's basename including ending NULL
739 : * @see keyBaseName(), keyGetBaseName()
740 : * @see keyName(), keyGetName(), keySetName()
741 : * @ingroup keyname
742 : */
743 56086 : ssize_t keyGetBaseNameSize (const Key * key)
744 : {
745 56086 : const char * baseName = keyBaseName (key);
746 56086 : if (!baseName) return -1;
747 :
748 56086 : return elektraStrLen (baseName);
749 : }
750 :
751 :
752 : /**
753 : * Calculate the basename of a key name and put it in @p returned finalizing
754 : * the string with NULL.
755 : *
756 : * Some examples:
757 : * - basename of @c system/some/keyname is @c keyname
758 : * - basename of @c "user/tmp/some key" is @c "some key"
759 : *
760 : * @param key the key to extract basename from
761 : * @param returned a pre-allocated buffer to store the basename
762 : * @param maxSize size of the @p returned buffer
763 : * @return number of bytes copied to @p returned
764 : * @retval 1 on empty name
765 : * @retval -1 on NULL pointers
766 : * @retval -1 when maxSize is 0 or larger than SSIZE_MAX
767 : * @see keyBaseName(), keyGetBaseNameSize()
768 : * @see keyName(), keyGetName(), keySetName()
769 : * @ingroup keyname
770 : */
771 1140 : ssize_t keyGetBaseName (const Key * key, char * returned, size_t maxSize)
772 : {
773 1140 : if (!key) return -1;
774 1138 : if (!returned) return -1;
775 1136 : if (!maxSize) return -1;
776 :
777 1132 : if (maxSize > SSIZE_MAX) return -1;
778 1130 : ssize_t maxSSize = maxSize;
779 :
780 1130 : if (!key->key)
781 : {
782 2 : returned[0] = 0;
783 2 : return 1;
784 : }
785 :
786 1128 : ssize_t baseSize = keyGetBaseNameSize (key);
787 1128 : if (maxSSize < baseSize)
788 : {
789 : return -1;
790 : }
791 :
792 1120 : const char * baseName = keyBaseName (key);
793 :
794 1120 : if (!baseName)
795 : {
796 : return -1;
797 : }
798 :
799 1120 : strncpy (returned, baseName, baseSize);
800 1120 : return baseSize;
801 : }
802 :
803 :
804 : /**
805 : * Adds @p baseName (that will be escaped) to the current key name.
806 : *
807 : * A new baseName will be added, no other part of the key name will be
808 : * affected.
809 : *
810 : * Assumes that @p key is a directory and will append @p baseName to it.
811 : * The function adds the path separator for concatenating.
812 : *
813 : * So if @p key has name @c "system/dir1/dir2" and this method is called with
814 : * @p baseName @c "mykey", the resulting key will have the name
815 : * @c "system/dir1/dir2/mykey".
816 : *
817 : * When @p baseName is 0 nothing will happen and the size of the name is returned.
818 : *
819 : * The escaping rules apply as in @link keyname above @endlink.
820 : *
821 : * A simple example is:
822 : * @snippet keyBasename.c add base basic
823 : *
824 : * E.g. if you add . it will be escaped:
825 : * @snippet testabi_key.c base1 add
826 : *
827 : * @see keySetBaseName() to set a base name
828 : * @see keySetName() to set a new name.
829 : *
830 : * @param key the key object to work with
831 : * @param baseName the string to append to the name
832 : * @return the size in bytes of the new key name including the ending NULL
833 : * @retval -1 if the key had no name
834 : * @retval -1 on NULL pointers
835 : * @retval -1 if key was inserted to a keyset before
836 : * @retval -1 on allocation errors
837 : * @ingroup keyname
838 : *
839 : */
840 879662 : ssize_t keyAddBaseName (Key * key, const char * baseName)
841 : {
842 879662 : if (!key) return -1;
843 879636 : if (!baseName) return key->keySize;
844 879634 : if (test_bit (key->flags, KEY_FLAG_RO_NAME)) return -1;
845 879630 : if (!key->key) return -1;
846 :
847 879625 : char * escaped = elektraMalloc (strlen (baseName) * 2 + 2);
848 879625 : elektraEscapeKeyNamePart (baseName, escaped);
849 879625 : size_t len = strlen (escaped);
850 879625 : if (!strcmp (key->key, "/"))
851 : {
852 151773 : key->keySize += len;
853 : }
854 : else
855 : {
856 727852 : key->keySize += len + 1;
857 : }
858 :
859 879625 : const size_t newSize = key->keySize * 2;
860 879625 : if (test_bit (key->flags, KEY_FLAG_MMAP_KEY))
861 : {
862 : // key was in mmap region, clear flag and trigger malloc instead of realloc
863 0 : key->key = elektraMalloc (newSize);
864 0 : clear_bit (key->flags, (keyflag_t) KEY_FLAG_MMAP_KEY);
865 : }
866 : else
867 : {
868 879625 : if (-1 == elektraRealloc ((void **) &key->key, newSize)) return -1;
869 : }
870 :
871 879625 : if (!key->key)
872 : {
873 0 : elektraFree (escaped);
874 0 : return -1;
875 : }
876 :
877 879625 : if (strcmp (key->key, "/"))
878 : {
879 727852 : key->key[key->keySize - len - 2] = KDB_PATH_SEPARATOR;
880 : }
881 879625 : memcpy (key->key + key->keySize - len - 1, escaped, len);
882 :
883 879625 : elektraFree (escaped);
884 :
885 879625 : elektraFinalizeName (key);
886 :
887 879625 : return key->keySize;
888 : }
889 :
890 : /**
891 : * @internal
892 : *
893 : * @brief Used by keyAddName
894 : *
895 : * Will remove one level of key, even if key->key is not null terminated
896 : * also handles cascading keys and sets avoidSlash properly.
897 : *
898 : * @param key to remove one level
899 : * @param [out] avoidSlash set to 1 if / is already present (cascading)
900 : */
901 411237 : static void elektraRemoveOneLevel (Key * key, int * avoidSlash)
902 : {
903 411237 : int levels = 0;
904 411237 : char * x = key->key;
905 411237 : size_t xsize = 0;
906 411237 : size_t sizeOfLastLevel = 0;
907 411237 : char * const last = &key->key[key->keySize];
908 411237 : const char save = *last;
909 411237 : *last = 0;
910 :
911 2418027 : while (*(x = keyNameGetOneLevel (x + xsize, &xsize)))
912 : {
913 2006790 : sizeOfLastLevel = xsize;
914 2006790 : levels++;
915 : }
916 :
917 411237 : if (levels > 1)
918 : {
919 410378 : key->keySize -= sizeOfLastLevel + 1;
920 410378 : key->key[key->keySize] = 0;
921 : }
922 859 : else if (*key->key == '/') // cascading key
923 : {
924 : // strip down to root
925 100 : key->keySize = 1;
926 100 : *avoidSlash = 1;
927 : }
928 411237 : *last = save;
929 411237 : }
930 :
931 : /**
932 : * @brief Add an already escaped name to the keyname.
933 : *
934 : * The same way as in keySetName() this method finds the canonical pathname:
935 : * - it will ignore /./
936 : * - it will remove a level when /../ is used
937 : * - it will remove multiple slashes ////
938 : *
939 : * For example:
940 : * @snippet keyName.c add name
941 : *
942 : * Unlike keySetName() it adds relative to the previous name and
943 : * cannot change the namespace of a key.
944 : * For example:
945 : * @snippet keyName.c namespace
946 : *
947 : * The passed name needs to be valid according the @link keyname key name rules @endlink.
948 : * It is not allowed to:
949 : * - be empty
950 : * - end with unequal number of \\
951 : *
952 : * @param key the key where a name should be added
953 : * @param newName the new name to append
954 : *
955 : * @since 0.8.11
956 : *
957 : * @retval size of the new key
958 : * @retval -1 if key is a null pointer or did not have a valid name before
959 : * @retval -1 if newName is not a valid escaped name
960 : * @retval -1 on allocation errors
961 : * @retval -1 if key was inserted to a keyset before
962 : * @retval 0 if nothing was done because newName had only slashes, is too short, is empty or is null
963 : * @ingroup keyname
964 : */
965 7320626 : ssize_t keyAddName (Key * key, const char * newName)
966 : {
967 7320626 : if (!key) return -1;
968 7320624 : if (test_bit (key->flags, KEY_FLAG_RO_NAME)) return -1;
969 7320620 : if (!key->key) return -1;
970 7320619 : if (!strcmp (key->key, "")) return -1;
971 7320617 : if (!newName) return 0;
972 7320611 : size_t const nameSize = elektraStrLen (newName);
973 7320611 : if (nameSize < 2) return 0;
974 7320404 : if (!elektraValidateKeyName (newName, nameSize)) return -1;
975 :
976 7320394 : const size_t origSize = key->keySize;
977 7320394 : const size_t newSize = (origSize + nameSize) * 2;
978 :
979 7320394 : if (test_bit (key->flags, KEY_FLAG_MMAP_KEY))
980 : {
981 : // key was in mmap region, clear flag and trigger malloc instead of realloc
982 0 : key->key = elektraMalloc (newSize);
983 0 : clear_bit (key->flags, (keyflag_t) KEY_FLAG_MMAP_KEY);
984 : }
985 : else
986 : {
987 7320394 : if (-1 == elektraRealloc ((void **) &key->key, newSize)) return -1;
988 : }
989 :
990 7320394 : if (!key->key) return -1;
991 :
992 7320394 : size_t size = 0;
993 7320394 : const char * p = newName;
994 7320394 : int avoidSlash = 0;
995 :
996 7320394 : if (*key->key == '/') avoidSlash = key->keySize == 2;
997 :
998 7320394 : --key->keySize; // loop assumes that key->key[key->keySize] is last character and not NULL
999 :
1000 : /* iterate over each single folder name removing repeated '/', . and .. */
1001 30368617 : while (*(p = keyNameGetOneLevel (p + size, &size)))
1002 : {
1003 15727829 : if (size == 1 && strncmp (p, ".", 1) == 0)
1004 : {
1005 982 : continue; /* just ignore current directory */
1006 : }
1007 15726847 : else if (size == 2 && strncmp (p, "..", 2) == 0) /* give away one level*/
1008 : {
1009 411237 : elektraRemoveOneLevel (key, &avoidSlash);
1010 411237 : continue;
1011 : }
1012 :
1013 15315610 : if (!avoidSlash)
1014 : {
1015 : /* Add a '/' to the end of key name */
1016 14875583 : key->key[key->keySize] = KDB_PATH_SEPARATOR;
1017 14875583 : key->keySize++;
1018 : }
1019 : else
1020 : {
1021 440027 : avoidSlash = 0;
1022 : }
1023 :
1024 : /* carefully append basenames */
1025 15315610 : char * d = key->key + key->keySize;
1026 15315610 : memcpy (d, p, size);
1027 15315610 : key->keySize += size;
1028 : }
1029 :
1030 7320394 : ++key->keySize; /*for \\0 ending*/
1031 :
1032 7320394 : elektraFinalizeName (key);
1033 :
1034 7320394 : return origSize == key->keySize ? 0 : key->keySize;
1035 : }
1036 :
1037 :
1038 : /**
1039 : * Sets @c baseName as the new basename for @c key.
1040 : *
1041 : * Only the baseName will be affected and no other part of the key.
1042 : *
1043 : * A simple example is:
1044 : * @snippet keyBasename.c set base basic
1045 : *
1046 : * All text after the last @c '/' in the @p key keyname is erased and
1047 : * @p baseName is appended.
1048 : * If @p baseName is 0 (NULL), then the last part of the keyname is
1049 : * removed without replacement.
1050 : *
1051 : * Let us suppose @p key has name @c "system/dir1/dir2/key1". If @p baseName
1052 : * is @c "key2", the resulting key name will be @c "system/dir1/dir2/key2".
1053 : * If @p baseName is 0 (NULL), the resulting key name will
1054 : * be @c "system/dir1/dir2".
1055 : * If @p baseName is empty, the resulting key name will
1056 : * be @c "system/dir1/dir2/%", where @c "%" denotes an empty base name,
1057 : * as also shown in the following code:
1058 : *
1059 : * @snippet testabi_key.c base2
1060 : *
1061 : * keySetBaseName() does proper escaping on the supplied name argument.
1062 : *
1063 : * You can use character sequences as @c baseName (e.g. @c "." (dot), @c ".."
1064 : * (dot-dot), @c "%" (empty basename)). They will be properly escaped
1065 : * and will not have their usual meaning.
1066 : *
1067 : * @see keyname for more details on special names
1068 : *
1069 : * If you want to add and not change the basename, use keyAddBaseName()
1070 : * instead. If you do not want escaping, use keyAddName() instead.
1071 : *
1072 : * @see keyAddBaseName() to add a basename instead of changing it
1073 : * @see keyAddName() to add a name without escaping
1074 : * @see keySetName() to set a completely new name
1075 : *
1076 : * To add an inactive key name, use:
1077 : * @snippet testabi_key.c base1
1078 : *
1079 : * @param key the key object to work with
1080 : * @param baseName the string used to overwrite the basename of the key
1081 : * @return the size in bytes of the new key name
1082 : * @retval -1 on NULL pointers in key
1083 : * @retval -1 if key was inserted to a keyset before
1084 : * @retval -1 on allocation errors
1085 : * @ingroup keyname
1086 : */
1087 328730 : ssize_t keySetBaseName (Key * key, const char * baseName)
1088 : {
1089 328730 : if (!key) return -1;
1090 328730 : if (test_bit (key->flags, KEY_FLAG_RO_NAME)) return -1;
1091 328724 : if (!key->key) return -1;
1092 :
1093 328721 : size_t size = 0;
1094 328721 : char * searchBaseName = 0;
1095 328721 : size_t searchBaseSize = 0;
1096 328721 : char * p = key->key;
1097 :
1098 1811214 : while (*(p = keyNameGetOneLevel (p + size, &size)))
1099 : {
1100 1153772 : searchBaseName = p;
1101 1153772 : searchBaseSize = size + 1;
1102 : }
1103 :
1104 328721 : if (!searchBaseName || searchBaseName == key->key)
1105 : {
1106 : return -1;
1107 : }
1108 :
1109 : // truncate the key
1110 328390 : key->keySize -= searchBaseSize;
1111 :
1112 328390 : if (!baseName)
1113 : {
1114 : // Avoid deleting the last / of a cascading key by increasing the size by one again
1115 8586 : key->keySize += (1 == key->keySize) && (KEY_NS_CASCADING == keyGetNamespace (key));
1116 :
1117 : // just remove base name, so we are finished
1118 8586 : elektraFinalizeName (key);
1119 8586 : return key->keySize;
1120 : }
1121 :
1122 319804 : char * escaped = elektraMalloc (strlen (baseName) * 2 + 2);
1123 319804 : elektraEscapeKeyNamePart (baseName, escaped);
1124 319804 : size_t sizeEscaped = elektraStrLen (escaped);
1125 :
1126 319804 : const size_t newSize = (key->keySize + sizeEscaped) * 2;
1127 319804 : if (test_bit (key->flags, KEY_FLAG_MMAP_KEY))
1128 : {
1129 : // key was in mmap region, clear flag and trigger malloc instead of realloc
1130 0 : key->key = elektraMalloc (newSize);
1131 0 : clear_bit (key->flags, (keyflag_t) KEY_FLAG_MMAP_KEY);
1132 : }
1133 : else
1134 : {
1135 319804 : if (-1 == elektraRealloc ((void **) &key->key, newSize)) return -1;
1136 : }
1137 :
1138 319804 : if (!key->key)
1139 : {
1140 0 : elektraFree (escaped);
1141 0 : return -1;
1142 : }
1143 :
1144 319804 : key->key[key->keySize - 1] = KDB_PATH_SEPARATOR;
1145 319804 : memcpy (key->key + key->keySize, escaped, sizeEscaped);
1146 :
1147 319804 : elektraFree (escaped);
1148 :
1149 319804 : key->keySize += sizeEscaped;
1150 319804 : elektraFinalizeName (key);
1151 :
1152 319804 : return key->keySize;
1153 : }
1154 :
1155 : /**
1156 : * For currently valid namespaces see #elektraNamespace.
1157 : *
1158 : * @since 0.8.10
1159 : * Added method to kdbproposal.h
1160 : *
1161 : * To handle every possible cases (including namespaces) a key can have:
1162 : * @snippet namespace.c namespace
1163 : *
1164 : * To loop over all valid namespaces use:
1165 : * @snippet namespace.c loop
1166 : *
1167 : * @note This method might be enhanced. You do not have any guarantee
1168 : * that, when for a specific name #KEY_NS_META
1169 : * is returned today, that it still will be returned after the next
1170 : * recompilation. So make sure that your compiler gives you a warning
1171 : * for unhandled switches (gcc: -Wswitch or -Wswitch-enum if you
1172 : * want to handle default) and look out for those warnings.
1173 : *
1174 : * @param key the key object to work with
1175 : * @return the namespace of a key.
1176 : */
1177 1883591 : elektraNamespace keyGetNamespace (const Key * key)
1178 : {
1179 1883591 : if (!key) return KEY_NS_NONE;
1180 1883381 : return keyGetNameNamespace (key->key);
1181 : }
1182 :
1183 :
1184 : /**
1185 : * @}
1186 : */
|