cfengine  3.15.4
About: CFEngine is a configuration management system for configuring and maintaining Unix-like computers (using an own high level policy language). Community version.
  Fossies Dox: cfengine-3.15.4.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

class.c
Go to the documentation of this file.
1 /*
2  Copyright 2019 Northern.tech AS
3 
4  This file is part of CFEngine 3 - written and maintained by Northern.tech AS.
5 
6  This program is free software; you can redistribute it and/or modify it
7  under the terms of the GNU General Public License as published by the
8  Free Software Foundation; version 3.
9 
10  This program is distributed in the hope that it will be useful,
11  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13  GNU General Public License for more details.
14 
15  You should have received a copy of the GNU General Public License
16  along with this program; if not, write to the Free Software
17  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
18 
19  To the extent this program is licensed as part of the Enterprise
20  versions of CFEngine, the applicable Commercial Open Source License
21  (COSL) may apply to this file if you as a licensee so wish it. See
22  included file COSL.txt.
23 */
24 #include <class.h>
25 
26 #include <map.h>
27 #include <alloc.h>
28 #include <string_lib.h> /* String*() */
29 #include <regex.h> /* CompileRegex,StringMatchFullWithPrecompiledRegex */
30 #include <files_names.h>
31 
32 
33 static void ClassDestroy(Class *cls); /* forward declaration */
34 
35 static void ClassDestroy_untyped(void *p)
36 {
37  ClassDestroy(p);
38 }
39 
40 
41 /**
42  Define ClassMap.
43  Key: a string which is always the fully qualified class name,
44  for example "default:127_0_0_1"
45 */
46 
48 
49 TYPED_MAP_DEFINE(Class, char *, Class *,
52  free,
54 
56 {
58 };
59 
61 {
63  char *ns;
64  bool is_hard;
65  bool is_soft;
66 };
67 
68 
69 /**
70  * @param #tags is a comma separated string of words.
71  * Both "" or NULL are equivalent.
72  */
73 static void ClassInit(Class *cls,
74  const char *ns, const char *name,
75  bool is_soft, ContextScope scope, const char *tags)
76 {
77  if (ns == NULL || strcmp(ns, "default") == 0)
78  {
79  cls->ns = NULL;
80  }
81  else
82  {
83  cls->ns = xstrdup(ns);
84  }
85 
86  cls->name = xstrdup(name);
88 
89  cls->is_soft = is_soft;
90  cls->scope = scope;
91 
92  cls->tags = StringSetFromString(tags, ',');
93  if (!is_soft && !StringSetContains(cls->tags, "hardclass"))
94  {
95  StringSetAdd(cls->tags, xstrdup("hardclass"));
96  }
97 }
98 
99 static void ClassDestroySoft(Class *cls)
100 {
101  if (cls)
102  {
103  free(cls->ns);
104  free(cls->name);
105  StringSetDestroy(cls->tags);
106  }
107 }
108 
109 static void ClassDestroy(Class *cls)
110 {
111  if (cls)
112  {
113  ClassDestroySoft(cls);
114  free(cls);
115  }
116 }
117 
119 {
120  ClassTable *table = xmalloc(sizeof(*table));
121 
122  table->classes = ClassMapNew();
123 
124  return table;
125 }
126 
128 {
129  if (table)
130  {
131  ClassMapDestroy(table->classes);
132  free(table);
133  }
134 }
135 
137  const char *ns, const char *name,
138  bool is_soft, ContextScope scope, const char *tags)
139 {
140  assert(name);
141  assert(is_soft || (!ns || strcmp("default", ns) == 0)); // hard classes should have default namespace
142  assert(is_soft || scope == CONTEXT_SCOPE_NAMESPACE); // hard classes cannot be local
143 
144  if (ns == NULL)
145  {
146  ns = "default";
147  }
148 
149  Class *cls = xmalloc(sizeof(*cls));
150  ClassInit(cls, ns, name, is_soft, scope, tags);
151 
152  /* (cls->name != name) because canonification has happened. */
153  char *fullname = StringConcatenate(3, ns, ":", cls->name);
154 
155  Log(LOG_LEVEL_DEBUG, "Setting %sclass: %s",
156  is_soft ? "" : "hard ",
157  fullname);
158 
159  return ClassMapInsert(table->classes, fullname, cls);
160 }
161 
162 Class *ClassTableGet(const ClassTable *table, const char *ns, const char *name)
163 {
164  if (ns == NULL)
165  {
166  ns = "default";
167  }
168 
169  char fullname[ strlen(ns) + 1 + strlen(name) + 1 ];
170  xsnprintf(fullname, sizeof(fullname), "%s:%s", ns, name);
171 
172  return ClassMapGet(table->classes, fullname);
173 }
174 
175 Class *ClassTableMatch(const ClassTable *table, const char *regex)
176 {
177  ClassTableIterator *it = ClassTableIteratorNew(table, NULL, true, true);
178  Class *cls = NULL;
179 
180  pcre *pattern = CompileRegex(regex);
181  if (pattern == NULL)
182  {
183  // TODO: perhaps pcre has can give more info on this error?
184  Log(LOG_LEVEL_ERR, "Unable to pcre compile regex '%s'", regex);
185  return NULL;
186  }
187 
188  while ((cls = ClassTableIteratorNext(it)))
189  {
190  bool matched;
191  if (cls->ns)
192  {
193  char *class_expr = ClassRefToString(cls->ns, cls->name);
194  matched = StringMatchFullWithPrecompiledRegex(pattern, class_expr);
195  free(class_expr);
196  }
197  else
198  {
199  matched = StringMatchFullWithPrecompiledRegex(pattern, cls->name);
200  }
201 
202  if (matched)
203  {
204  break;
205  }
206  }
207 
208  pcre_free(pattern);
209 
211  return cls;
212 }
213 
214 bool ClassTableRemove(ClassTable *table, const char *ns, const char *name)
215 {
216  if (ns == NULL)
217  {
218  ns = "default";
219  }
220 
221  char fullname[ strlen(ns) + 1 + strlen(name) + 1 ];
222  xsnprintf(fullname, sizeof(fullname), "%s:%s", ns, name);
223 
224  return ClassMapRemove(table->classes, fullname);
225 }
226 
228 {
229  bool has_classes = (ClassMapSize(table->classes) > 0);
230  ClassMapClear(table->classes);
231  return has_classes;
232 }
233 
235  const char *ns,
236  bool is_hard, bool is_soft)
237 {
238  ClassTableIterator *iter = xmalloc(sizeof(*iter));
239 
240  iter->ns = ns ? xstrdup(ns) : NULL;
241  iter->iter = MapIteratorInit(table->classes->impl);
242  iter->is_soft = is_soft;
243  iter->is_hard = is_hard;
244 
245  return iter;
246 }
247 
249 {
250  MapKeyValue *keyvalue;
251 
252  while ((keyvalue = MapIteratorNext(&iter->iter)) != NULL)
253  {
254  Class *cls = keyvalue->value;
255 
256  /* Make sure we never store "default" as namespace in the ClassTable,
257  * instead we have always ns==NULL in that case. */
258  CF_ASSERT_FIX(cls->ns == NULL ||
259  strcmp(cls->ns, "default") != 0,
260  (cls->ns = NULL),
261  "Class table contained \"default\" namespace,"
262  " should never happen!");
263 
264  const char *key_ns = cls->ns ? cls->ns : "default";
265 
266  if (iter->ns && strcmp(key_ns, iter->ns) != 0)
267  {
268  continue;
269  }
270 
271  if (iter->is_soft && !iter->is_soft)
272  {
273  continue;
274  }
275  if (iter->is_hard && !iter->is_hard)
276  {
277  continue;
278  }
279 
280  return cls;
281  }
282 
283  return NULL;
284 }
285 
287 {
288  if (iter)
289  {
290  free(iter->ns);
291  free(iter);
292  }
293 }
294 
295 ClassRef ClassRefParse(const char *expr)
296 {
297  char *name_start = strchr(expr, ':');
298  if (!name_start)
299  {
300  return (ClassRef) { .ns = NULL, .name = xstrdup(expr) };
301  }
302  else
303  {
304  char *ns = NULL;
305  if ((name_start - expr) > 0)
306  {
307  ns = xstrndup(expr, name_start - expr);
308  }
309  else
310  {
311  // this would be invalid syntax
312  ns = xstrdup("");
313  }
314  char *name = xstrdup(name_start + 1);
315  return (ClassRef) { .ns = ns, .name = name };
316  }
317 }
318 
319 char *ClassRefToString(const char *ns, const char *name)
320 {
321  assert(name != NULL);
322 
323  if (ns == NULL ||
324  strcmp("default", ns) == 0)
325  {
326  return xstrdup(name);
327  }
328  else
329  {
330  return StringConcatenate(3, ns, ":", name);
331  }
332 }
333 
335 {
336  return ref.ns != NULL;
337 }
338 
339 void ClassRefQualify(ClassRef *ref, const char *ns)
340 {
341  free(ref->ns);
342  ref->ns = xstrdup(ns);
343 }
344 
346 {
347  free(ref.ns);
348  free(ref.name);
349 }
void * xmalloc(size_t size)
Definition: alloc-mini.c:46
char * xstrdup(const char *str)
Definition: alloc-mini.c:56
char * xstrndup(const char *str, size_t n)
Definition: alloc.c:61
ContextScope
Definition: cf3.defs.h:945
@ CONTEXT_SCOPE_NAMESPACE
Definition: cf3.defs.h:946
void free(void *)
static void ClassDestroy(Class *cls)
Definition: class.c:109
void ClassTableDestroy(ClassTable *table)
Definition: class.c:127
Class * ClassTableGet(const ClassTable *table, const char *ns, const char *name)
Definition: class.c:162
void ClassRefQualify(ClassRef *ref, const char *ns)
Definition: class.c:339
bool ClassMapInsert(const ClassMap *map, char *key, Class *value)
Definition: class.c:53
static void ClassDestroySoft(Class *cls)
Definition: class.c:99
ClassMap * ClassMapNew(void)
Definition: class.c:53
ClassTableIterator * ClassTableIteratorNew(const ClassTable *table, const char *ns, bool is_hard, bool is_soft)
Definition: class.c:234
static void ClassDestroy_untyped(void *p)
Definition: class.c:35
static void ClassInit(Class *cls, const char *ns, const char *name, bool is_soft, ContextScope scope, const char *tags)
Definition: class.c:73
ClassTable * ClassTableNew(void)
Definition: class.c:118
char * ClassRefToString(const char *ns, const char *name)
Definition: class.c:319
void ClassRefDestroy(ClassRef ref)
Definition: class.c:345
ClassRef ClassRefParse(const char *expr)
Definition: class.c:295
void ClassMapDestroy(ClassMap *map)
Definition: class.c:53
bool ClassTableRemove(ClassTable *table, const char *ns, const char *name)
Definition: class.c:214
bool ClassMapRemove(const ClassMap *map, const char *key)
Definition: class.c:53
bool ClassRefIsQualified(ClassRef ref)
Definition: class.c:334
void ClassMapClear(ClassMap *map)
Definition: class.c:53
bool ClassTablePut(ClassTable *table, const char *ns, const char *name, bool is_soft, ContextScope scope, const char *tags)
Definition: class.c:136
Class * ClassTableMatch(const ClassTable *table, const char *regex)
Definition: class.c:175
size_t ClassMapSize(const ClassMap *map)
Definition: class.c:53
Class * ClassMapGet(const ClassMap *map, const char *key)
Definition: class.c:53
void ClassTableIteratorDestroy(ClassTableIterator *iter)
Definition: class.c:286
bool ClassTableClear(ClassTable *table)
Definition: class.c:227
Class * ClassTableIteratorNext(ClassTableIterator *iter)
Definition: class.c:248
#define NULL
Definition: getopt1.c:56
void Log(LogLevel level, const char *fmt,...)
Definition: logging.c:409
@ LOG_LEVEL_ERR
Definition: logging.h:42
@ LOG_LEVEL_DEBUG
Definition: logging.h:47
MapIterator MapIteratorInit(Map *map)
Definition: map.c:325
MapKeyValue * MapIteratorNext(MapIterator *i)
Definition: map.c:343
#define TYPED_MAP_DECLARE(Prefix, KeyType, ValueType)
Definition: map.h:116
#define TYPED_MAP_DEFINE(Prefix, KeyType, ValueType, hash_fn, equal_fn, destroy_key_fn, destroy_value_fn)
Definition: map.h:134
void xsnprintf(char *str, size_t str_size, const char *format,...)
Definition: misc_lib.c:114
#define CF_ASSERT_FIX(condition, fix,...)
Definition: misc_lib.h:64
pcre * CompileRegex(const char *regex)
Definition: regex.c:37
bool StringMatchFullWithPrecompiledRegex(pcre *pattern, const char *str)
Definition: regex.c:121
StringSet * StringSetFromString(const char *str, char delimiter)
Definition: set.c:179
bool StringSetContains(const StringSet *set, const char *element)
Definition: set.c:34
void StringSetDestroy(StringSet *set)
Definition: set.c:34
void StringSetAdd(const StringSet *set, char *element)
Definition: set.c:34
bool StringEqual_untyped(const void *a, const void *b)
Definition: string_lib.c:306
unsigned int StringHash_untyped(const void *str, unsigned int seed)
Definition: string_lib.c:114
char * StringConcatenate(size_t count, const char *first,...)
Definition: string_lib.c:348
void CanonifyNameInPlace(char *s)
Definition: string_lib.c:1574
Definition: class.c:47
Map * impl
Definition: class.c:47
Definition: class.h:59
char * name
Definition: class.h:61
char * ns
Definition: class.h:60
MapIterator iter
Definition: class.c:62
ClassMap * classes
Definition: class.c:57
Definition: class.h:31
char * ns
Definition: class.h:32
char * name
Definition: class.h:33
bool is_soft
Definition: class.h:36
StringSet * tags
Definition: class.h:37
ContextScope scope
Definition: class.h:35
void * value
Definition: map_common.h:36