Line data Source code
1 : /**
2 : * @file
3 : *
4 : * @brief
5 : *
6 : * @copyright BSD License (see LICENSE.md or https://www.libelektra.org)
7 : */
8 :
9 : #include "xmltool.h"
10 :
11 : #include <string.h>
12 :
13 :
14 : /**
15 : * @internal
16 : *
17 : * Calculates the common parent to all keys in @p ks.
18 : *
19 : * This is a c-helper function, you need not implement it in bindings.
20 : *
21 : * Given the @p ks KeySet, calculates the parent name for all the keys.
22 : * So if @p ks contains this keys:
23 : *
24 : * @code
25 : * system/sw/xorg/Monitors/Monitor1/vrefresh
26 : * system/sw/xorg/Monitors/Monitor1/hrefresh
27 : * system/sw/xorg/Devices/Device1/driver
28 : * system/sw/xorg/Devices/Device1/mode
29 : * @endcode
30 : *
31 : * The common parent is @p system/sw/xorg .
32 : *
33 : * On the other hand, if we have this KeySet:
34 : *
35 : * @code
36 : * system/some/thing
37 : * system/other/thing
38 : * user/unique/thing
39 : * @endcode
40 : *
41 : * No common parent is possible, so @p returnedCommonParent will contain nothing.
42 : *
43 : * @param working the Keyset to work with
44 : * @param returnedCommonParent a pre-allocated buffer that will receive the
45 : * common parent, if found
46 : * @param maxSize size of the pre-allocated @p returnedCommonParent buffer
47 : * @return size in bytes of the parent name, or 0 if there is no common parent,
48 : * or -1 to indicate an error, then @p errno must be checked.
49 : */
50 6 : ssize_t ksGetCommonParentName (const KeySet * working, char * returnedCommonParent, size_t maxSize)
51 : {
52 6 : size_t parentSize = 0;
53 6 : Key * current = 0;
54 : cursor_t cinit;
55 : KeySet * ks;
56 : ssize_t sMaxSize;
57 :
58 6 : if (maxSize > SSIZE_MAX) return -1;
59 6 : sMaxSize = maxSize;
60 :
61 6 : cinit = ksGetCursor (working);
62 6 : ks = (KeySet *) working;
63 :
64 6 : if (ksGetSize (ks) < 1) return 0;
65 :
66 6 : ksRewind (ks);
67 6 : current = ksNext (ks);
68 6 : if (keyGetNameSize (current) > sMaxSize)
69 : {
70 : /*errno=KDB_ERR_TRUNC;*/
71 0 : returnedCommonParent[0] = 0;
72 0 : return -1;
73 : }
74 :
75 6 : strcpy (returnedCommonParent, keyName (current));
76 6 : parentSize = elektraStrLen (returnedCommonParent);
77 :
78 6 : while (*returnedCommonParent)
79 : {
80 20 : ksRewind (ks);
81 75 : while ((current = ksNext (ks)) != 0)
82 : {
83 : /* Test if a key doesn't match */
84 51 : if (memcmp (returnedCommonParent, keyName (current), parentSize - 1)) break;
85 : }
86 20 : if (current)
87 : {
88 : /* some key failed to be a child */
89 : /* parent will be the parent of current parent... */
90 16 : char * delim = 0;
91 :
92 : // TODO: does not honor escaped characters
93 16 : if ((delim = strrchr (returnedCommonParent, KDB_PATH_SEPARATOR)))
94 : {
95 14 : *delim = 0;
96 14 : parentSize = elektraStrLen (returnedCommonParent);
97 : }
98 : else
99 : {
100 2 : *returnedCommonParent = 0;
101 2 : parentSize = 0;
102 2 : break; /* Better don't make comparison with parentSize-1 now */
103 : }
104 : }
105 : else
106 : {
107 : /* All keys matched (current==0) */
108 : /* We have our common parent to return in commonParent */
109 4 : ksSetCursor (ks, cinit);
110 4 : return parentSize;
111 : }
112 : }
113 2 : ksSetCursor (ks, cinit);
114 2 : return parentSize; /* if reached, will be zero */
115 : }
|