Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief Reference methods.
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : */
8 :
9 : #include "kdbease.h"
10 :
11 : #include "kdbhelper.h"
12 :
13 : #include <string.h>
14 :
15 :
16 : /**
17 : * Check whether a reference is redundant (i.e. it can be expressed in less characters) or not.
18 : *
19 : * This can be used to give a warning to users, because redundant references are often
20 : * mistakes. Using "../some/key/../path" instead of "../some/path" may indicate, that either
21 : * a mistake was made while editing, or the concept of references was misunderstood.
22 : *
23 : * @param reference the reference to check
24 : * @retval 1 if the reference is redundant
25 : * @retval 0 otherwise
26 : */
27 88 : int elektraIsReferenceRedundant (const char * reference)
28 : {
29 88 : const char * cur = reference;
30 188 : while (strncmp (cur, "../", 3) == 0)
31 : {
32 12 : cur += 3;
33 : }
34 :
35 88 : return strstr (reference, "/./") != NULL || strstr (cur, "/../") != NULL ? 1 : 0;
36 : }
37 :
38 : /**
39 : * Resolve reference into a full keyname.
40 : *
41 : * References operate like UNIX paths, with some additions:
42 : * - '.' refers to the current key
43 : * - '..' refers to the parent of the current key
44 : * - '@' refers to the parentKey of KDB
45 : * - references starting with anything but './', '../' and '@/' as absolute,
46 : * only embedded '/./' and '/../' as well as '/.' and '/..' at the end will
47 : * be resolved (like in any keySetName call)
48 : *
49 : * @param reference The reference to resolve
50 : * @param baseKey The key identified by the reference "./"
51 : * @param parentKey The key identified by the reference "@/"
52 : *
53 : * @return a newly allocated string, containing the full keyname;
54 : * has to be disposed with elektraFree()
55 : */
56 94 : char * elektraResolveReference (const char * reference, const Key * baseKey, const Key * parentKey)
57 : {
58 94 : if (reference == NULL || strlen (reference) == 0)
59 : {
60 : return NULL;
61 : }
62 :
63 94 : Key * fullReference = keyNew ("", KEY_END);
64 :
65 94 : if (elektraStrNCmp (reference, "@/", 2) == 0)
66 : {
67 4 : keySetName (fullReference, keyName (parentKey));
68 4 : keyAddName (fullReference, &reference[2]);
69 : }
70 90 : else if (elektraStrNCmp (reference, "./", 2) == 0)
71 : {
72 4 : keySetName (fullReference, keyName (baseKey));
73 4 : keyAddName (fullReference, &reference[2]);
74 : }
75 86 : else if (elektraStrNCmp (reference, "../", 3) == 0)
76 : {
77 14 : keySetName (fullReference, keyName (baseKey));
78 14 : keyAddName (fullReference, reference);
79 : }
80 : else
81 : {
82 72 : keySetName (fullReference, reference);
83 : }
84 :
85 94 : char * result = elektraStrDup (keyName (fullReference));
86 94 : keyDel (fullReference);
87 :
88 94 : return result;
89 : }
|