Coverage Report

Created: 2026-04-04 06:09

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
19
/*
20
 * Functions to help find particular sections of the CIB
21
 */
22
23
// Map CIB element names to their parent elements and XPath searches
24
static struct {
25
    const char *name;   // Name of this CIB element
26
    const char *parent; // CIB element that this element is a child of
27
    const char *path;   // XPath to find this CIB element
28
} cib_sections[] = {
29
    {
30
        // This first entry is also the default if a NULL is compared
31
        PCMK_XE_CIB,
32
        NULL,
33
        "//" PCMK_XE_CIB
34
    },
35
    {
36
        PCMK_XE_STATUS,
37
        "/" PCMK_XE_CIB,
38
        "//" PCMK_XE_CIB "/" PCMK_XE_STATUS
39
    },
40
    {
41
        PCMK_XE_CONFIGURATION,
42
        "/" PCMK_XE_CIB,
43
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION
44
    },
45
    {
46
        PCMK_XE_CRM_CONFIG,
47
        "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
48
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_CRM_CONFIG
49
    },
50
    {
51
        PCMK_XE_NODES,
52
        "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
53
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_NODES
54
    },
55
    {
56
        PCMK_XE_RESOURCES,
57
        "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
58
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_RESOURCES
59
    },
60
    {
61
        PCMK_XE_CONSTRAINTS,
62
        "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
63
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_CONSTRAINTS
64
    },
65
    {
66
        PCMK_XE_OP_DEFAULTS,
67
        "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
68
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_OP_DEFAULTS
69
    },
70
    {
71
        PCMK_XE_RSC_DEFAULTS,
72
        "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
73
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_RSC_DEFAULTS
74
    },
75
    {
76
        PCMK_XE_ACLS,
77
        "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
78
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_ACLS
79
    },
80
    {
81
        PCMK_XE_FENCING_TOPOLOGY,
82
        "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
83
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_FENCING_TOPOLOGY
84
    },
85
    {
86
        PCMK_XE_TAGS,
87
        "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
88
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_TAGS
89
    },
90
    {
91
        PCMK_XE_ALERTS,
92
        "/" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION,
93
        "//" PCMK_XE_CIB "/" PCMK_XE_CONFIGURATION "/" PCMK_XE_ALERTS
94
    },
95
    {
96
        PCMK__XE_ALL,
97
        NULL,
98
        "//" PCMK_XE_CIB
99
    },
100
};
101
102
/*!
103
 * \brief Get the relative XPath needed to find a specified CIB element name
104
 *
105
 * \param[in] element_name  Name of CIB element
106
 *
107
 * \return XPath for finding \p element_name in CIB XML (or NULL if unknown)
108
 * \note The return value is constant and should not be freed.
109
 */
110
const char *
111
pcmk_cib_xpath_for(const char *element_name)
112
0
{
113
0
    for (int lpc = 0; lpc < PCMK__NELEM(cib_sections); lpc++) {
114
        // A NULL element_name will match the first entry
115
0
        if (pcmk__str_eq(element_name, cib_sections[lpc].name,
116
0
                         pcmk__str_null_matches)) {
117
0
            return cib_sections[lpc].path;
118
0
        }
119
0
    }
120
0
    return NULL;
121
0
}
122
123
/*!
124
 * \internal
125
 * \brief Get the absolute XPath needed to find a specified CIB element name
126
 *
127
 * \param[in] element  Name of CIB element
128
 *
129
 * \return XPath for finding \p element in CIB XML (or \c NULL if unknown)
130
 */
131
const char *
132
pcmk__cib_abs_xpath_for(const char *element)
133
0
{
134
0
    const char *xpath = pcmk_cib_xpath_for(element);
135
136
    // XPaths returned by pcmk_cib_xpath_for() are relative (starting with "//")
137
0
    return ((xpath != NULL)? (xpath + 1) : NULL);
138
0
}
139
140
/*!
141
 * \brief Get the parent element name of a given CIB element name
142
 *
143
 * \param[in] element_name  Name of CIB element
144
 *
145
 * \return Parent element of \p element_name (or NULL if none or unknown)
146
 * \note The return value is constant and should not be freed.
147
 */
148
const char *
149
pcmk_cib_parent_name_for(const char *element_name)
150
0
{
151
0
    for (int lpc = 0; lpc < PCMK__NELEM(cib_sections); lpc++) {
152
        // A NULL element_name will match the first entry
153
0
        if (pcmk__str_eq(element_name, cib_sections[lpc].name,
154
0
                         pcmk__str_null_matches)) {
155
0
            return cib_sections[lpc].parent;
156
0
        }
157
0
    }
158
0
    return NULL;
159
0
}
160
161
/*!
162
 * \brief Find an element in the CIB
163
 *
164
 * \param[in] cib           Top-level CIB XML to search
165
 * \param[in] element_name  Name of CIB element to search for
166
 *
167
 * \return XML element in \p cib corresponding to \p element_name
168
 *         (or \p cib itself if element is unknown or not found)
169
 */
170
xmlNode *
171
pcmk_find_cib_element(xmlNode *cib, const char *element_name)
172
0
{
173
0
    return pcmk__xpath_find_one(cib->doc, pcmk_cib_xpath_for(element_name),
174
0
                                LOG_TRACE);
175
0
}
176
177
/*!
178
 * \internal
179
 * \brief Check that the feature set in the CIB is supported on this node
180
 *
181
 * \param[in] new_version   PCMK_XA_CRM_FEATURE_SET attribute from the CIB
182
 */
183
int
184
pcmk__check_feature_set(const char *cib_version)
185
0
{
186
0
    if ((cib_version != NULL)
187
0
        && (pcmk__compare_versions(cib_version, CRM_FEATURE_SET) > 0)) {
188
0
        return EPROTONOSUPPORT;
189
0
    }
190
191
0
    return pcmk_rc_ok;
192
0
}