Clean up RPM spec for newer distributions
[clumanager.git] / librhcm / xmlwrap.c
blob748dab58704b1c5ac45b1ffbada79018304b3306
1 /*
2 Copyright Red Hat, Inc. 2002-2003
4 This program is free software; you can redistribute it and/or modify it
5 under the terms of the GNU General Public License as published by the
6 Free Software Foundation; either version 2, or (at your option) any
7 later version.
9 This program is distributed in the hope that it will be useful, but
10 WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; see the file COPYING. If not, write to the
16 Free Software Foundation, Inc., 675 Mass Ave, Cambridge,
17 MA 02139, USA.
19 /** @file
20 * CFG_xxx API -> XML Config API Wrapper.
22 * XXX NOT THREAD SAFE - need to return copies of strings!
23 * XXX Needs Doxygenification.
25 #include <xmlconfig.h>
26 #include <xmlwrap.h>
28 #ifndef NO_SHARED_IO
29 #include <clushared.h>
30 #include <sharedstate.h>
31 #endif
33 #include <pthread.h>
34 #include <namespace.h>
35 #include <clushared.h>
36 #include <errno.h>
38 static xmlDocPtr config_db = NULL;
39 static pthread_mutex_t config_db_mutex = PTHREAD_MUTEX_INITIALIZER;
41 int CFG_Initialized(void);
42 int CFG_Loaded(void);
43 int CFG_Set(const char *token, char *value);
44 int CFG_Get(const char *token, char *dflt, char **value);
45 int CFG_ReadFile(const char *filename);
46 int CFG_Read(void);
47 int CFG_WriteFile(const char *filename);
48 int CFG_Write(void);
49 int CFG_Remove(const char *token);
50 int CFG_RemoveMatch(const char *token, int mtype);
51 void CFG_Destroy(void);
52 xmlDocPtr CFG_Get_Pointer(void);
55 * Non-locked internals so we don't have to worry about recursive nonportabtle
56 * pthread_mutex_t...
58 static int cfg_readfile_nt(const char *filename);
59 #ifndef NO_SHARED_IO
60 static int cfg_readbuffer_nt(void);
61 #endif
62 static void cfg_destroy_nt(void);
65 /**
66 * Is there an initialized config db?
67 * @return 1 if a config database is present, 0 if not
68 * @see CFG_Initialized
70 int
71 CFG_Initialized(void)
73 pthread_mutex_lock(&config_db_mutex);
74 if (config_db) {
75 pthread_mutex_unlock(&config_db_mutex);
76 return 1;
78 pthread_mutex_unlock(&config_db_mutex);
79 return 0;
83 /**
84 * Is the subsystem initialized?
85 * XXX this probably should do something different from CFG_Initialized()
86 * @return 1 if a config database is present, 0 if not
87 * @see CFG_Initialized
89 int
90 CFG_Loaded(void)
92 pthread_mutex_lock(&config_db_mutex);
93 if (config_db) {
94 pthread_mutex_unlock(&config_db_mutex);
95 return 1;
97 pthread_mutex_unlock(&config_db_mutex);
98 return 0;
102 * Sets a token to a value in a config database database.
104 * @param token The token in the form of "tag%sub1%subsub1%attribute"
105 * @param value The value (string) to set.
106 * @return CFG_BAD_KEY if the key is invalid, CFG_FALSE if
107 * it wasn't possible to store the value, or CFG_OK on
108 * success.
111 CFG_Set(const char *token, char *value)
113 int rv;
115 pthread_mutex_lock(&config_db_mutex);
116 if (!config_db) {
117 pthread_mutex_unlock(&config_db_mutex);
118 return CFG_FALSE;
121 rv = xtree_set(config_db, token, value);
122 pthread_mutex_unlock(&config_db_mutex);
124 switch (rv) {
125 case -1:
126 return CFG_BAD_KEY;
127 case 0:
128 return CFG_OK;
131 return CFG_FALSE;
136 * Retrieve a value from the configuration database, given a token.
138 * @param token The token in the form of "tag%sub1%subsub1%attribute"
139 * @param dflt The default value, if any, to return.
140 * @param value A pointer to a string pointer. Do not free the memory
141 * returned! XXX This is broken and NOT thread safe. ;(
142 * It should return a newly allocated string which can
143 * be freed.
144 * @return CFG_BAD_KEY if the key was invalid, CFG_DEFAULT if no
145 * match was found but a default was specified, CFG_OK
146 on success, or CFG_FALSE if no value was found.
149 CFG_Get(const char *token, char *dflt, char **value)
151 int rv;
152 char *val_priv;
154 pthread_mutex_lock(&config_db_mutex);
155 rv = xtree_get(config_db, token, dflt, &val_priv);
156 pthread_mutex_unlock(&config_db_mutex);
158 switch(rv) {
159 case -1:
160 return CFG_BAD_KEY;
161 case 0:
162 if (!strcasecmp(val_priv, "none")) {
163 if (dflt) {
164 *value = dflt;
165 /* "none" is a reserved word here */
166 return CFG_DEFAULT;
168 *value = NULL;
169 return CFG_FALSE;
172 if (value) {
173 *value = val_priv;
174 if (*value == dflt)
175 return CFG_DEFAULT;
178 return CFG_OK;
179 case 1:
180 return CFG_DEFAULT;
183 return CFG_FALSE;
187 static int
188 cfg_readfile_nt(const char *filename)
190 cfg_destroy_nt();
191 return xtree_readfile(filename, &config_db);
196 * Read a local config file into memory.
198 * @param filename File to read.
199 * @return CFG_OK on success, CFG_PARSE_FAILED if the file could
200 * could not be parsed, or CFG_FALSE for other errors (ie,
201 * the file didn't exist)
202 * @see CFG_Read
205 CFG_ReadFile(const char *filename)
207 int rv;
208 char *realfn;
210 pthread_mutex_lock(&config_db_mutex);
211 if (filename && strlen(filename))
212 realfn = (char *)filename;
213 else
214 realfn = CLU_CONFIG_FILE;
216 rv = cfg_readfile_nt(realfn);
217 pthread_mutex_unlock(&config_db_mutex);
219 switch(rv) {
220 case 0:
221 return CFG_OK;
222 case -1:
223 return CFG_PARSE_FAILED;
225 return CFG_FALSE;
229 #ifndef NO_SHARED_IO
230 static int
231 cfg_readbuffer_nt(void)
233 char *buffer;
234 int sz, rv;
235 SharedHeader hdr;
237 if (shared_storage_init() == -1)
238 return -1;
240 rv = sh_stat(NS_D_CLUSTER "/" NS_F_CONFIG, &hdr);
241 if (rv == -1)
242 return -1;
244 sz = (int)hdr.h_length;
245 buffer = malloc(sz+1);
246 if (!buffer)
247 return -1;
249 cfg_destroy_nt();
250 memset(buffer,0,sz+1);
251 if (sh_read_atomic(NS_D_CLUSTER "/" NS_F_CONFIG, buffer, sz) == -1) {
252 printf("failed reading " NS_D_CLUSTER "/" NS_F_CONFIG ": %s\n",
253 strerror(errno));
255 free(buffer);
256 return -1;
259 rv = xtree_readbuffer(buffer, sz+1, &config_db);
261 free(buffer);
262 return rv;
264 #endif
268 * Read the configuration file from shared state into memory. This requires
269 * shared_storage_init() to be called first!
271 * @return CFG_OK on success, CFG_PARSE_FAILED if the file could
272 * could not be parsed.
275 CFG_Read(void)
277 #ifndef NO_SHARED_IO
278 int rv;
280 pthread_mutex_lock(&config_db_mutex);
281 rv = cfg_readbuffer_nt();
282 pthread_mutex_unlock(&config_db_mutex);
284 if (rv == -1)
285 return CFG_PARSE_FAILED;
286 return CFG_OK;
287 #else
288 errno = -ENOSYS;
289 return CFG_FALSE;
290 #endif
294 static void
295 cfg_destroy_nt(void)
297 if (config_db) {
298 xmlFreeDoc(config_db);
299 config_db = NULL;
305 * Nuke the in-memory configuration database.
307 void
308 CFG_Destroy(void)
310 pthread_mutex_lock(&config_db_mutex);
311 cfg_destroy_nt();
312 pthread_mutex_unlock(&config_db_mutex);
317 * Write the contents of the in-memory configuration database to a file.
319 * @param filename File to write.
320 * @return CFG_FALSE on failure, CFG_OK on success.
321 * @see CFG_WriteBuffer, CFG_Write
324 CFG_WriteFile(const char *filename)
326 int rv, esv;
327 pthread_mutex_lock(&config_db_mutex);
328 rv = xtree_writefile(filename, config_db);
329 esv = errno;
330 pthread_mutex_unlock(&config_db_mutex);
332 if (rv == -1) {
333 errno = esv;
334 return CFG_FALSE;
337 return CFG_OK;
342 * Write the contents of the in-memory configuration database to a buffer.
343 * The buffer is allocated in-line, and must be freed by the caller..
345 * @param buf Return buffer pointer.
346 * @param buflen Return buffer size.
347 * @return CFG_FALSE on failure, CFG_OK on success.
348 * @see CFG_WriteFile, CFG_Write
351 CFG_WriteBuffer(char **buf, size_t *buflen)
353 int rv;
355 pthread_mutex_lock(&config_db_mutex);
356 rv = xtree_writebuffer(config_db, buf, buflen);
357 pthread_mutex_unlock(&config_db_mutex);
359 if (rv == -1)
360 return CFG_FALSE;
362 return CFG_OK;
367 * Writes the configuration database from memory to shared state.
369 * @return CFG_FALSE on failure, CFG_OK on success.
370 * @see CFG_WriteFile
373 CFG_Write(void)
375 #ifndef NO_SHARED_IO
376 int rv;
377 size_t bufsize;
378 char *buf = NULL;
380 pthread_mutex_lock(&config_db_mutex);
381 rv = xtree_writebuffer(config_db, &buf, &bufsize);
382 pthread_mutex_unlock(&config_db_mutex);
384 if (rv == -1) {
385 if (buf)
386 free(buf);
387 return CFG_FALSE;
390 rv = sh_write_atomic(NS_D_CLUSTER "/" NS_F_CONFIG, buf, bufsize);
391 if (rv == -1) {
392 rv = errno;
393 free(buf);
394 errno = rv;
395 return CFG_FALSE;
397 free(buf);
399 return CFG_OK;
400 #else
401 errno = -ENOSYS;
402 return CFG_FALSE;
403 #endif
408 * Remove a token from the in-memory config database.
410 * @param token Token to remove.
411 * @return CFG_FALSE on failure, or CFG_OK on success.
414 CFG_Remove(const char * token)
416 int rv;
417 pthread_mutex_lock(&config_db_mutex);
418 rv = xtree_del(config_db, token);
419 pthread_mutex_unlock(&config_db_mutex);
421 return (rv == -1)?CFG_FALSE:CFG_OK;
425 int _xtree_del(xmlAttrPtr attr);
427 CFG_RemoveMatch(const char *pattern, int mtype)
429 token_list_head head;
430 token_list_node *cur;
432 pthread_mutex_lock(&config_db_mutex);
434 /* Build the list of tokens... */
435 if (xtree_tl_build(config_db, &head, pattern, mtype) == -1) {
436 pthread_mutex_unlock(&config_db_mutex);
437 return CFG_FALSE;
440 /* Remove them! */
441 for (cur = head.tqh_first; cur; cur = cur->tl_chain.tqe_next) {
442 if (_xtree_del(cur->tl_terminal) == -1) {
443 xtree_tl_free(&head);
444 pthread_mutex_unlock(&config_db_mutex);
445 return CFG_FALSE;
449 xtree_tl_free(&head);
450 pthread_mutex_unlock(&config_db_mutex);
452 return CFG_OK;
456 CFG_Struct *
457 CFG_MemBackup(void)
459 CFG_Struct *cs = NULL;
461 cs = malloc(sizeof(*cs));
462 if (!cs)
463 return NULL;
465 pthread_mutex_lock(&config_db_mutex);
466 cs->cs_tree = config_db;
467 config_db = NULL;
468 pthread_mutex_unlock(&config_db_mutex);
470 return cs;
474 void
475 CFG_MemRestore(CFG_Struct *cs)
477 if (!cs)
478 return;
480 pthread_mutex_lock(&config_db_mutex);
481 if (config_db)
482 cfg_destroy_nt();
484 config_db = cs->cs_tree;
485 pthread_mutex_unlock(&config_db_mutex);
486 free(cs);
490 void
491 CFG_MemBackupKill(CFG_Struct *cs)
493 if (!cs)
494 return;
496 xmlFreeDoc(cs->cs_tree);
497 free(cs);
502 * List operations Totally the opposite of thread safe.
504 CFG_List *
505 CFG_ListCreate(const char *m_pat, int m_type)
507 CFG_List *list = NULL;
508 token_list_head *head = NULL;
510 head = malloc(sizeof(*head));
511 if (!head)
512 return NULL;
514 list = malloc(sizeof(*list));
515 if (!list) {
516 free(head);
517 return NULL;
520 if (xtree_tl_build(config_db, head, m_pat, m_type) <= 0) {
521 free(list);
522 free(head);
523 return NULL;
526 list->cl_head = head;
527 list->cl_cur = head->tqh_first;
529 return list;
533 void
534 CFG_ListDestroy(CFG_List *list)
536 if (!list)
537 return;
539 if (list->cl_head) {
540 xtree_tl_free(list->cl_head);
541 free(list->cl_head);
543 free(list);
548 CFG_ListNext(CFG_List *list)
550 if (list->cl_cur->tl_chain.tqe_next) {
551 list->cl_cur = list->cl_cur->tl_chain.tqe_next;
552 return 1;
554 return 0;
559 CFG_ListMore(CFG_List *list)
561 if (!list || !list->cl_cur)
562 return 0;
564 return (!!(list->cl_cur->tl_chain.tqe_next));
568 void
569 CFG_ListRewind(CFG_List *list)
571 list->cl_cur = list->cl_head->tqh_first;