Coverage Report

Created: 2026-01-03 06:24

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/pacemaker/lib/common/cib.c
Line
Count
Source
1
/*
2
 * Original copyright 2004 International Business Machines
3
 * Later changes copyright 2008-2025 the Pacemaker project contributors
4
 *
5
 * The version control history for this file may have further details.
6
 *
7
 * This source code is licensed under the GNU Lesser General Public License
8
 * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY.
9
 */
10
11
#include <crm_internal.h>
12
13
#include <stdio.h>
14
#include <libxml/tree.h>    // xmlNode
15
16
#include <crm/common/xml.h>
17
#include <crm/common/cib.h>
18
#include <crm/common/cib_internal.h>
19
20
/*
21
 * Functions to help find particular sections of the CIB
22
 */
23
24
// Map CIB element names to their parent elements and XPath searches
25
static struct {
26
    const char *name;   // Name of this CIB element
27
    const char *parent; // CIB element that this element is a child of
28
    const char *path;   // XPath to find this CIB element
29
} cib_sections[] = {
30
    {
31
        // This first entry is also the default if a NULL is compared
32
        PCMK_XE_CIB,
33
        NULL,
34
        "//" PCMK_XE_CIB
35
    },
36
    {
37
        PCMK_XE_STATUS,
38
        "/" PCMK_XE_CIB,
39
        "//" PCMK_XE_CIB "/" PCMK_XE_STATUS
40
    },
41
    {
42
        PCMK_XE_CONFIGURATION,
43
        "/" PCMK_XE_CIB,
44
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION
45
    },
46
    {
47
        PCMK_XE_CRM_CONFIG,
48
        "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
49
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_CRM_CONFIG
50
    },
51
    {
52
        PCMK_XE_NODES,
53
        "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
54
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_NODES
55
    },
56
    {
57
        PCMK_XE_RESOURCES,
58
        "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
59
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_RESOURCES
60
    },
61
    {
62
        PCMK_XE_CONSTRAINTS,
63
        "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
64
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_CONSTRAINTS
65
    },
66
    {
67
        PCMK_XE_OP_DEFAULTS,
68
        "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
69
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_OP_DEFAULTS
70
    },
71
    {
72
        PCMK_XE_RSC_DEFAULTS,
73
        "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
74
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_RSC_DEFAULTS
75
    },
76
    {
77
        PCMK_XE_ACLS,
78
        "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
79
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_ACLS
80
    },
81
    {
82
        PCMK_XE_FENCING_TOPOLOGY,
83
        "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
84
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_FENCING_TOPOLOGY
85
    },
86
    {
87
        PCMK_XE_TAGS,
88
        "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
89
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_TAGS
90
    },
91
    {
92
        PCMK_XE_ALERTS,
93
        "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
94
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_ALERTS
95
    },
96
    {
97
        PCMK__XE_ALL,
98
        NULL,
99
        "//" PCMK_XE_CIB
100
    },
101
};
102
103
/*!
104
 * \brief Get the relative XPath needed to find a specified CIB element name
105
 *
106
 * \param[in] element_name  Name of CIB element
107
 *
108
 * \return XPath for finding \p element_name in CIB XML (or NULL if unknown)
109
 * \note The return value is constant and should not be freed.
110
 */
111
const char *
112
pcmk_cib_xpath_for(const char *element_name)
113
0
{
114
0
    for (int lpc = 0; lpc < PCMK__NELEM(cib_sections); lpc++) {
115
        // A NULL element_name will match the first entry
116
0
        if (pcmk__str_eq(element_name, cib_sections[lpc].name,
117
0
                         pcmk__str_null_matches)) {
118
0
            return cib_sections[lpc].path;
119
0
        }
120
0
    }
121
0
    return NULL;
122
0
}
123
124
/*!
125
 * \internal
126
 * \brief Get the absolute XPath needed to find a specified CIB element name
127
 *
128
 * \param[in] element  Name of CIB element
129
 *
130
 * \return XPath for finding \p element in CIB XML (or \c NULL if unknown)
131
 */
132
const char *
133
pcmk__cib_abs_xpath_for(const char *element)
134
0
{
135
0
    const char *xpath = pcmk_cib_xpath_for(element);
136
137
    // XPaths returned by pcmk_cib_xpath_for() are relative (starting with "//")
138
0
    return ((xpath != NULL)? (xpath + 1) : NULL);
139
0
}
140
141
/*!
142
 * \brief Get the parent element name of a given CIB element name
143
 *
144
 * \param[in] element_name  Name of CIB element
145
 *
146
 * \return Parent element of \p element_name (or NULL if none or unknown)
147
 * \note The return value is constant and should not be freed.
148
 */
149
const char *
150
pcmk_cib_parent_name_for(const char *element_name)
151
0
{
152
0
    for (int lpc = 0; lpc < PCMK__NELEM(cib_sections); lpc++) {
153
        // A NULL element_name will match the first entry
154
0
        if (pcmk__str_eq(element_name, cib_sections[lpc].name,
155
0
                         pcmk__str_null_matches)) {
156
0
            return cib_sections[lpc].parent;
157
0
        }
158
0
    }
159
0
    return NULL;
160
0
}
161
162
/*!
163
 * \brief Find an element in the CIB
164
 *
165
 * \param[in,out] cib           Top-level CIB XML to search
166
 * \param[in]     element_name  Name of CIB element to search for
167
 *
168
 * \return XML element in \p cib corresponding to \p element_name
169
 *         (or \p cib itself if element is unknown or not found)
170
 */
171
xmlNode *
172
pcmk_find_cib_element(xmlNode *cib, const char *element_name)
173
0
{
174
0
    return pcmk__xpath_find_one(cib->doc, pcmk_cib_xpath_for(element_name),
175
0
                                LOG_TRACE);
176
0
}
177
178
/*!
179
 * \internal
180
 * \brief Check that the feature set in the CIB is supported on this node
181
 *
182
 * \param[in] new_version   PCMK_XA_CRM_FEATURE_SET attribute from the CIB
183
 */
184
int
185
pcmk__check_feature_set(const char *cib_version)
186
0
{
187
0
    if ((cib_version != NULL)
188
0
        && (pcmk__compare_versions(cib_version, CRM_FEATURE_SET) > 0)) {
189
0
        return EPROTONOSUPPORT;
190
0
    }
191
192
0
    return pcmk_rc_ok;
193
0
}