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
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,
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>
29 #include <clushared.h>
30 #include <sharedstate.h>
34 #include <namespace.h>
35 #include <clushared.h>
38 static xmlDocPtr config_db
= NULL
;
39 static pthread_mutex_t config_db_mutex
= PTHREAD_MUTEX_INITIALIZER
;
41 int CFG_Initialized(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
);
47 int CFG_WriteFile(const char *filename
);
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
58 static int cfg_readfile_nt(const char *filename
);
60 static int cfg_readbuffer_nt(void);
62 static void cfg_destroy_nt(void);
66 * Is there an initialized config db?
67 * @return 1 if a config database is present, 0 if not
68 * @see CFG_Initialized
73 pthread_mutex_lock(&config_db_mutex
);
75 pthread_mutex_unlock(&config_db_mutex
);
78 pthread_mutex_unlock(&config_db_mutex
);
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
92 pthread_mutex_lock(&config_db_mutex
);
94 pthread_mutex_unlock(&config_db_mutex
);
97 pthread_mutex_unlock(&config_db_mutex
);
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
111 CFG_Set(const char *token
, char *value
)
115 pthread_mutex_lock(&config_db_mutex
);
117 pthread_mutex_unlock(&config_db_mutex
);
121 rv
= xtree_set(config_db
, token
, value
);
122 pthread_mutex_unlock(&config_db_mutex
);
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
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
)
154 pthread_mutex_lock(&config_db_mutex
);
155 rv
= xtree_get(config_db
, token
, dflt
, &val_priv
);
156 pthread_mutex_unlock(&config_db_mutex
);
162 if (!strcasecmp(val_priv
, "none")) {
165 /* "none" is a reserved word here */
188 cfg_readfile_nt(const char *filename
)
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)
205 CFG_ReadFile(const char *filename
)
210 pthread_mutex_lock(&config_db_mutex
);
211 if (filename
&& strlen(filename
))
212 realfn
= (char *)filename
;
214 realfn
= CLU_CONFIG_FILE
;
216 rv
= cfg_readfile_nt(realfn
);
217 pthread_mutex_unlock(&config_db_mutex
);
223 return CFG_PARSE_FAILED
;
231 cfg_readbuffer_nt(void)
237 if (shared_storage_init() == -1)
240 rv
= sh_stat(NS_D_CLUSTER
"/" NS_F_CONFIG
, &hdr
);
244 sz
= (int)hdr
.h_length
;
245 buffer
= malloc(sz
+1);
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",
259 rv
= xtree_readbuffer(buffer
, sz
+1, &config_db
);
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.
280 pthread_mutex_lock(&config_db_mutex
);
281 rv
= cfg_readbuffer_nt();
282 pthread_mutex_unlock(&config_db_mutex
);
285 return CFG_PARSE_FAILED
;
298 xmlFreeDoc(config_db
);
305 * Nuke the in-memory configuration database.
310 pthread_mutex_lock(&config_db_mutex
);
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
)
327 pthread_mutex_lock(&config_db_mutex
);
328 rv
= xtree_writefile(filename
, config_db
);
330 pthread_mutex_unlock(&config_db_mutex
);
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
)
355 pthread_mutex_lock(&config_db_mutex
);
356 rv
= xtree_writebuffer(config_db
, buf
, buflen
);
357 pthread_mutex_unlock(&config_db_mutex
);
367 * Writes the configuration database from memory to shared state.
369 * @return CFG_FALSE on failure, CFG_OK on success.
380 pthread_mutex_lock(&config_db_mutex
);
381 rv
= xtree_writebuffer(config_db
, &buf
, &bufsize
);
382 pthread_mutex_unlock(&config_db_mutex
);
390 rv
= sh_write_atomic(NS_D_CLUSTER
"/" NS_F_CONFIG
, buf
, bufsize
);
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
)
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
);
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
);
449 xtree_tl_free(&head
);
450 pthread_mutex_unlock(&config_db_mutex
);
459 CFG_Struct
*cs
= NULL
;
461 cs
= malloc(sizeof(*cs
));
465 pthread_mutex_lock(&config_db_mutex
);
466 cs
->cs_tree
= config_db
;
468 pthread_mutex_unlock(&config_db_mutex
);
475 CFG_MemRestore(CFG_Struct
*cs
)
480 pthread_mutex_lock(&config_db_mutex
);
484 config_db
= cs
->cs_tree
;
485 pthread_mutex_unlock(&config_db_mutex
);
491 CFG_MemBackupKill(CFG_Struct
*cs
)
496 xmlFreeDoc(cs
->cs_tree
);
502 * List operations Totally the opposite of thread safe.
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
));
514 list
= malloc(sizeof(*list
));
520 if (xtree_tl_build(config_db
, head
, m_pat
, m_type
) <= 0) {
526 list
->cl_head
= head
;
527 list
->cl_cur
= head
->tqh_first
;
534 CFG_ListDestroy(CFG_List
*list
)
540 xtree_tl_free(list
->cl_head
);
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
;
559 CFG_ListMore(CFG_List
*list
)
561 if (!list
|| !list
->cl_cur
)
564 return (!!(list
->cl_cur
->tl_chain
.tqe_next
));
569 CFG_ListRewind(CFG_List
*list
)
571 list
->cl_cur
= list
->cl_head
->tqh_first
;