Page Menu
Home
ClusterLabs Projects
Search
Configure Global Search
Log In
Files
F2823067
No One
Temporary
Actions
View File
Edit File
Delete File
View Transforms
Subscribe
Mute Notifications
Flag For Later
Award Token
Size
95 KB
Referenced Files
None
Subscribers
None
View Options
diff --git a/exec/coroparse.c b/exec/coroparse.c
index b017aca9..08362cca 100644
--- a/exec/coroparse.c
+++ b/exec/coroparse.c
@@ -1,1703 +1,1704 @@
/*
* Copyright (c) 2006-2022 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Patrick Caulfield (pcaulfie@redhat.com)
* Jan Friesse (jfriesse@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the MontaVista Software, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <sys/types.h>
#include <sys/uio.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/un.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <dirent.h>
#include <libgen.h>
#include <limits.h>
#include <stddef.h>
#include <grp.h>
#include <pwd.h>
#include <qb/qblist.h>
#include <qb/qbutil.h>
#define LOGSYS_UTILS_ONLY 1
#include <corosync/logsys.h>
#include <corosync/icmap.h>
#include "main.h"
#include "util.h"
enum parser_cb_type {
PARSER_CB_START,
PARSER_CB_END,
PARSER_CB_SECTION_START,
PARSER_CB_SECTION_END,
PARSER_CB_ITEM,
};
enum main_cp_cb_data_state {
MAIN_CP_CB_DATA_STATE_NORMAL,
MAIN_CP_CB_DATA_STATE_TOTEM,
MAIN_CP_CB_DATA_STATE_INTERFACE,
MAIN_CP_CB_DATA_STATE_LOGGER_SUBSYS,
MAIN_CP_CB_DATA_STATE_UIDGID,
MAIN_CP_CB_DATA_STATE_LOGGING_DAEMON,
MAIN_CP_CB_DATA_STATE_MEMBER,
MAIN_CP_CB_DATA_STATE_QUORUM,
MAIN_CP_CB_DATA_STATE_QDEVICE,
MAIN_CP_CB_DATA_STATE_NODELIST,
MAIN_CP_CB_DATA_STATE_NODELIST_NODE,
MAIN_CP_CB_DATA_STATE_PLOAD,
MAIN_CP_CB_DATA_STATE_SYSTEM,
MAIN_CP_CB_DATA_STATE_RESOURCES,
MAIN_CP_CB_DATA_STATE_RESOURCES_SYSTEM,
MAIN_CP_CB_DATA_STATE_RESOURCES_PROCESS,
MAIN_CP_CB_DATA_STATE_RESOURCES_SYSTEM_MEMUSED,
MAIN_CP_CB_DATA_STATE_RESOURCES_PROCESS_MEMUSED
};
typedef int (*parser_cb_f)(const char *path,
char *key,
char *value,
enum main_cp_cb_data_state *state,
enum parser_cb_type type,
const char **error_string,
icmap_map_t config_map,
void *user_data);
struct key_value_list_item {
char *key;
char *value;
struct qb_list_head list;
};
struct main_cp_cb_data {
int linknumber;
char *bindnetaddr;
char *mcastaddr;
char *broadcast;
int mcastport;
int ttl;
int knet_link_priority;
int knet_ping_interval;
int knet_ping_timeout;
int knet_ping_precision;
int knet_pong_count;
int knet_pmtud_interval;
unsigned int knet_mtu;
char *knet_transport;
struct qb_list_head logger_subsys_items_head;
char *subsys;
char *logging_daemon_name;
struct qb_list_head member_items_head;
int node_number;
};
static int read_config_file_into_icmap(
const char **error_string, icmap_map_t config_map);
static char error_string_response[512];
static int uid_determine (const char *req_user)
{
int pw_uid = 0;
struct passwd passwd;
struct passwd* pwdptr = &passwd;
struct passwd* temp_pwd_pt;
char *pwdbuffer;
int pwdlinelen, rc;
long int id;
char *ep;
id = strtol(req_user, &ep, 10);
if (*req_user != '\0' && *ep == '\0' && id >= 0 && id <= UINT_MAX) {
return (id);
}
pwdlinelen = sysconf (_SC_GETPW_R_SIZE_MAX);
if (pwdlinelen == -1) {
pwdlinelen = 256;
}
pwdbuffer = malloc (pwdlinelen);
while ((rc = getpwnam_r (req_user, pwdptr, pwdbuffer, pwdlinelen, &temp_pwd_pt)) == ERANGE) {
char *n;
pwdlinelen *= 2;
if (pwdlinelen <= 32678) {
n = realloc (pwdbuffer, pwdlinelen);
if (n != NULL) {
pwdbuffer = n;
continue;
}
}
}
if (rc != 0) {
free (pwdbuffer);
sprintf (error_string_response, "getpwnam_r(): %s", strerror(rc));
return (-1);
}
if (temp_pwd_pt == NULL) {
free (pwdbuffer);
sprintf (error_string_response,
"The '%s' user is not found in /etc/passwd, please read the documentation.",
req_user);
return (-1);
}
pw_uid = passwd.pw_uid;
free (pwdbuffer);
return pw_uid;
}
static int gid_determine (const char *req_group)
{
int corosync_gid = 0;
struct group group;
struct group * grpptr = &group;
struct group * temp_grp_pt;
char *grpbuffer;
int grplinelen, rc;
long int id;
char *ep;
id = strtol(req_group, &ep, 10);
if (*req_group != '\0' && *ep == '\0' && id >= 0 && id <= UINT_MAX) {
return (id);
}
grplinelen = sysconf (_SC_GETGR_R_SIZE_MAX);
if (grplinelen == -1) {
grplinelen = 256;
}
grpbuffer = malloc (grplinelen);
while ((rc = getgrnam_r (req_group, grpptr, grpbuffer, grplinelen, &temp_grp_pt)) == ERANGE) {
char *n;
grplinelen *= 2;
if (grplinelen <= 32678) {
n = realloc (grpbuffer, grplinelen);
if (n != NULL) {
grpbuffer = n;
continue;
}
}
}
if (rc != 0) {
free (grpbuffer);
sprintf (error_string_response, "getgrnam_r(): %s", strerror(rc));
return (-1);
}
if (temp_grp_pt == NULL) {
free (grpbuffer);
sprintf (error_string_response,
"The '%s' group is not found in /etc/group, please read the documentation.",
req_group);
return (-1);
}
corosync_gid = group.gr_gid;
free (grpbuffer);
return corosync_gid;
}
static char *strchr_rs (const char *haystack, int byte)
{
const char *end_address = strchr (haystack, byte);
if (end_address) {
end_address += 1; /* skip past { or = */
while (*end_address == ' ' || *end_address == '\t' || (unsigned char)*end_address == 0xA0)
end_address++;
}
return ((char *) end_address);
}
int coroparse_configparse (icmap_map_t config_map, const char **error_string)
{
if (read_config_file_into_icmap(error_string, config_map)) {
return -1;
}
return 0;
}
static char *remove_whitespace(char *string, int remove_colon_and_brace)
{
char *start;
char *end;
start = string;
while (*start == ' ' || *start == '\t' || (unsigned char)*start == 0xA0)
start++;
end = start+(strlen(start))-1;
while ((*end == ' ' || *end == '\t' || (unsigned char)*end == 0xA0 || (remove_colon_and_brace && (*end == ':' || *end == '{'))) && end > start)
end--;
if (*end != '\0')
*(end + 1) = '\0';
return start;
}
static int parse_section(FILE *fp,
const char *fname,
int *line_no,
char *path,
const char **error_string,
int depth,
enum main_cp_cb_data_state state,
parser_cb_f parser_cb,
icmap_map_t config_map,
void *user_data)
{
char line[512];
int i;
char *loc;
int ignore_line;
char new_keyname[ICMAP_KEYNAME_MAXLEN];
static char formated_err[384];
const char *tmp_error_string;
if (strcmp(path, "") == 0) {
parser_cb("", NULL, NULL, &state, PARSER_CB_START, error_string, config_map, user_data);
}
tmp_error_string = NULL;
while (fgets (line, sizeof (line), fp)) {
(*line_no)++;
if (strlen(line) > 0) {
/*
* Check if complete line was read. Use feof to handle files
* without ending \n at the end of the file
*/
if ((line[strlen(line) - 1] != '\n') && !feof(fp)) {
tmp_error_string = "Line too long";
goto parse_error;
}
if (line[strlen(line) - 1] == '\n')
line[strlen(line) - 1] = '\0';
if (strlen (line) > 0 && line[strlen(line) - 1] == '\r')
line[strlen(line) - 1] = '\0';
}
/*
* Clear out white space and tabs
*/
for (i = strlen (line) - 1; i > -1; i--) {
if (line[i] == '\t' || line[i] == ' ' || (unsigned char)line[i] == 0xA0) {
line[i] = '\0';
} else {
break;
}
}
ignore_line = 1;
for (i = 0; i < strlen (line); i++) {
if (line[i] != '\t' && line[i] != ' ' && (unsigned char)line[i] != 0xA0) {
if (line[i] != '#')
ignore_line = 0;
break;
}
}
/*
* Clear out comments and empty lines
*/
if (ignore_line) {
continue;
}
/* New section ? */
if ((loc = strchr_rs (line, '{'))) {
char *section;
char *after_section;
enum main_cp_cb_data_state newstate;
*(loc-1) = '\0';
section = remove_whitespace(line, 1);
after_section = remove_whitespace(loc, 0);
if (strcmp(section, "") == 0) {
tmp_error_string = "Missing section name before opening bracket '{'";
goto parse_error;
}
if (strcmp(after_section, "") != 0) {
tmp_error_string = "Extra characters after opening bracket '{'";
goto parse_error;
}
if (strlen(path) + strlen(section) + 1 >= ICMAP_KEYNAME_MAXLEN) {
tmp_error_string = "Start of section makes total cmap path too long";
goto parse_error;
}
strcpy(new_keyname, path);
if (strcmp(path, "") != 0) {
strcat(new_keyname, ".");
}
strcat(new_keyname, section);
/* Only use the new state for items further down the stack */
newstate = state;
if (!parser_cb(new_keyname, NULL, NULL, &newstate, PARSER_CB_SECTION_START,
&tmp_error_string, config_map, user_data)) {
goto parse_error;
}
if (parse_section(fp, fname, line_no, new_keyname, error_string, depth + 1, newstate,
parser_cb, config_map, user_data))
return -1;
continue ;
}
/* New key/value */
if ((loc = strchr_rs (line, ':'))) {
char *key;
char *value;
*(loc-1) = '\0';
key = remove_whitespace(line, 1);
value = remove_whitespace(loc, 0);
if (strlen(path) + strlen(key) + 1 >= ICMAP_KEYNAME_MAXLEN) {
tmp_error_string = "New key makes total cmap path too long";
goto parse_error;
}
strcpy(new_keyname, path);
if (strcmp(path, "") != 0) {
strcat(new_keyname, ".");
}
strcat(new_keyname, key);
if (!parser_cb(new_keyname, key, value, &state, PARSER_CB_ITEM, &tmp_error_string,
config_map, user_data)) {
goto parse_error;
}
continue ;
}
if (strchr_rs (line, '}')) {
char *trimmed_line;
trimmed_line = remove_whitespace(line, 0);
if (strcmp(trimmed_line, "}") != 0) {
tmp_error_string = "Extra characters before or after closing bracket '}'";
goto parse_error;
}
if (depth == 0) {
tmp_error_string = "Unexpected closing brace";
goto parse_error;
}
if (!parser_cb(path, NULL, NULL, &state, PARSER_CB_SECTION_END, &tmp_error_string,
config_map, user_data)) {
goto parse_error;
}
return 0;
}
/*
* Line is not opening section, ending section or value -> error
*/
tmp_error_string = "Line is not opening or closing section or key value";
goto parse_error;
}
if (strcmp(path, "") != 0) {
tmp_error_string = "Missing closing brace";
goto parse_error;
}
if (strcmp(path, "") == 0) {
parser_cb("", NULL, NULL, &state, PARSER_CB_END, error_string, config_map, user_data);
}
return 0;
parse_error:
if (snprintf(formated_err, sizeof(formated_err), "parser error: %s:%u: %s", fname, *line_no,
tmp_error_string) >= sizeof(formated_err)) {
*error_string = "Can't format parser error message";
} else {
*error_string = formated_err;
}
return -1;
}
static int safe_atoq_range(icmap_value_types_t value_type, long long int *min_val, long long int *max_val)
{
switch (value_type) {
case ICMAP_VALUETYPE_INT8: *min_val = INT8_MIN; *max_val = INT8_MAX; break;
case ICMAP_VALUETYPE_UINT8: *min_val = 0; *max_val = UINT8_MAX; break;
case ICMAP_VALUETYPE_INT16: *min_val = INT16_MIN; *max_val = INT16_MAX; break;
case ICMAP_VALUETYPE_UINT16: *min_val = 0; *max_val = UINT16_MAX; break;
case ICMAP_VALUETYPE_INT32: *min_val = INT32_MIN; *max_val = INT32_MAX; break;
case ICMAP_VALUETYPE_UINT32: *min_val = 0; *max_val = UINT32_MAX; break;
+ case ICMAP_VALUETYPE_BOOLEAN: *min_val = 0; *max_val = 1; break;
default:
return (-1);
}
return (0);
}
/*
* Convert string str to long long int res. Type of result is target_type and currently only
* ICMAP_VALUETYPE_[U]INT[8|16|32] is supported.
* Return 0 on success, -1 on failure.
*/
static int safe_atoq(const char *str, long long int *res, icmap_value_types_t target_type)
{
long long int val;
long long int min_val, max_val;
char *endptr;
errno = 0;
val = strtoll(str, &endptr, 10);
if (errno == ERANGE) {
return (-1);
}
if (endptr == str) {
return (-1);
}
if (*endptr != '\0') {
return (-1);
}
if (safe_atoq_range(target_type, &min_val, &max_val) != 0) {
return (-1);
}
if (val < min_val || val > max_val) {
return (-1);
}
*res = val;
return (0);
}
static int str_to_ull(const char *str, unsigned long long int *res)
{
unsigned long long int val;
char *endptr;
errno = 0;
val = strtoull(str, &endptr, 10);
if (errno == ERANGE) {
return (-1);
}
if (endptr == str) {
return (-1);
}
if (*endptr != '\0') {
return (-1);
}
*res = val;
return (0);
}
static int handle_crypto_model(const char *val, const char **error_string)
{
if (util_is_valid_knet_crypto_model(val, NULL, 0,
"Invalid crypto model. Should be ", error_string) == 1) {
return (0);
} else {
return (-1);
}
}
static int handle_compress_model(const char *val, const char **error_string)
{
if (util_is_valid_knet_compress_model(val, NULL, 0,
"Invalid compression model. Should be ", error_string) == 1) {
return (0);
} else {
return (-1);
}
}
static int main_config_parser_cb(const char *path,
char *key,
char *value,
enum main_cp_cb_data_state *state,
enum parser_cb_type type,
const char **error_string,
icmap_map_t config_map,
void *user_data)
{
int ii;
long long int val;
long long int min_val, max_val;
icmap_value_types_t val_type = ICMAP_VALUETYPE_BINARY;
unsigned long long int ull;
int add_as_string;
char key_name[ICMAP_KEYNAME_MAXLEN + 1];
static char formated_err[256];
struct main_cp_cb_data *data = (struct main_cp_cb_data *)user_data;
struct key_value_list_item *kv_item;
struct qb_list_head *iter, *tmp_iter;
int uid, gid;
cs_error_t cs_err;
cs_err = CS_OK;
/*
* Formally this check is not needed because length is checked by parse_section
*/
if (strlen(path) >= sizeof(key_name)) {
if (snprintf(formated_err, sizeof(formated_err),
"Can't store path \"%s\" into key_name", path) >= sizeof(formated_err)) {
*error_string = "Can't format path into key_name error message";
} else {
*error_string = formated_err;
}
return (0);
}
/*
* Key_name is used in atoi_error/icmap_set_error, but many of icmap_set*
* are using path, so initialize key_name to valid value
*/
strncpy(key_name, path, sizeof(key_name) - 1);
switch (type) {
case PARSER_CB_START:
memset(data, 0, sizeof(struct main_cp_cb_data));
*state = MAIN_CP_CB_DATA_STATE_NORMAL;
break;
case PARSER_CB_END:
break;
case PARSER_CB_ITEM:
add_as_string = 1;
switch (*state) {
case MAIN_CP_CB_DATA_STATE_NORMAL:
break;
case MAIN_CP_CB_DATA_STATE_PLOAD:
if ((strcmp(path, "pload.count") == 0) ||
(strcmp(path, "pload.size") == 0)) {
val_type = ICMAP_VALUETYPE_UINT32;
if (safe_atoq(value, &val, val_type) != 0) {
goto atoi_error;
}
if ((cs_err = icmap_set_uint32_r(config_map, path, val)) != CS_OK) {
goto icmap_set_error;
}
add_as_string = 0;
}
break;
case MAIN_CP_CB_DATA_STATE_QUORUM:
if ((strcmp(path, "quorum.expected_votes") == 0) ||
(strcmp(path, "quorum.votes") == 0) ||
(strcmp(path, "quorum.last_man_standing_window") == 0) ||
(strcmp(path, "quorum.leaving_timeout") == 0)) {
val_type = ICMAP_VALUETYPE_UINT32;
if (safe_atoq(value, &val, val_type) != 0) {
goto atoi_error;
}
if ((cs_err = icmap_set_uint32_r(config_map, path, val)) != CS_OK) {
goto icmap_set_error;
}
add_as_string = 0;
}
if ((strcmp(path, "quorum.two_node") == 0) ||
(strcmp(path, "quorum.expected_votes_tracking") == 0) ||
(strcmp(path, "quorum.allow_downscale") == 0) ||
(strcmp(path, "quorum.wait_for_all") == 0) ||
(strcmp(path, "quorum.auto_tie_breaker") == 0) ||
(strcmp(path, "quorum.last_man_standing") == 0)) {
- val_type = ICMAP_VALUETYPE_UINT8;
+ val_type = ICMAP_VALUETYPE_BOOLEAN;
if (safe_atoq(value, &val, val_type) != 0) {
goto atoi_error;
}
if ((cs_err = icmap_set_uint8_r(config_map, path, val)) != CS_OK) {
goto icmap_set_error;
}
add_as_string = 0;
}
break;
case MAIN_CP_CB_DATA_STATE_QDEVICE:
if ((strcmp(path, "quorum.device.timeout") == 0) ||
(strcmp(path, "quorum.device.sync_timeout") == 0) ||
(strcmp(path, "quorum.device.votes") == 0)) {
val_type = ICMAP_VALUETYPE_UINT32;
if (safe_atoq(value, &val, val_type) != 0) {
goto atoi_error;
}
if ((cs_err = icmap_set_uint32_r(config_map, path, val)) != CS_OK) {
goto icmap_set_error;
}
add_as_string = 0;
}
if ((strcmp(path, "quorum.device.master_wins") == 0)) {
val_type = ICMAP_VALUETYPE_UINT8;
if (safe_atoq(value, &val, val_type) != 0) {
goto atoi_error;
}
if ((cs_err = icmap_set_uint8_r(config_map, path, val)) != CS_OK) {
goto icmap_set_error;
}
add_as_string = 0;
}
break;
case MAIN_CP_CB_DATA_STATE_TOTEM:
if ((strcmp(path, "totem.version") == 0) ||
(strcmp(path, "totem.nodeid") == 0) ||
(strcmp(path, "totem.threads") == 0) ||
(strcmp(path, "totem.token") == 0) ||
(strcmp(path, "totem.token_coefficient") == 0) ||
(strcmp(path, "totem.token_retransmit") == 0) ||
(strcmp(path, "totem.token_warning") == 0) ||
(strcmp(path, "totem.hold") == 0) ||
(strcmp(path, "totem.token_retransmits_before_loss_const") == 0) ||
(strcmp(path, "totem.join") == 0) ||
(strcmp(path, "totem.send_join") == 0) ||
(strcmp(path, "totem.consensus") == 0) ||
(strcmp(path, "totem.merge") == 0) ||
(strcmp(path, "totem.downcheck") == 0) ||
(strcmp(path, "totem.fail_recv_const") == 0) ||
(strcmp(path, "totem.seqno_unchanged_const") == 0) ||
(strcmp(path, "totem.rrp_token_expired_timeout") == 0) ||
(strcmp(path, "totem.rrp_problem_count_timeout") == 0) ||
(strcmp(path, "totem.rrp_problem_count_threshold") == 0) ||
(strcmp(path, "totem.rrp_problem_count_mcast_threshold") == 0) ||
(strcmp(path, "totem.rrp_autorecovery_check_timeout") == 0) ||
(strcmp(path, "totem.heartbeat_failures_allowed") == 0) ||
(strcmp(path, "totem.max_network_delay") == 0) ||
(strcmp(path, "totem.window_size") == 0) ||
(strcmp(path, "totem.max_messages") == 0) ||
(strcmp(path, "totem.miss_count_const") == 0) ||
(strcmp(path, "totem.knet_pmtud_interval") == 0) ||
(strcmp(path, "totem.knet_mtu") == 0) ||
(strcmp(path, "totem.knet_compression_threshold") == 0) ||
(strcmp(path, "totem.netmtu") == 0)) {
val_type = ICMAP_VALUETYPE_UINT32;
if (safe_atoq(value, &val, val_type) != 0) {
goto atoi_error;
}
if ((cs_err = icmap_set_uint32_r(config_map,path, val)) != CS_OK) {
goto icmap_set_error;
}
add_as_string = 0;
}
if (strcmp(path, "totem.knet_compression_level") == 0) {
val_type = ICMAP_VALUETYPE_INT32;
if (safe_atoq(value, &val, val_type) != 0) {
goto atoi_error;
}
if ((cs_err = icmap_set_int32_r(config_map, path, val)) != CS_OK) {
goto icmap_set_error;
}
add_as_string = 0;
}
if (strcmp(path, "totem.config_version") == 0) {
if (str_to_ull(value, &ull) != 0) {
goto atoi_error;
}
if ((cs_err = icmap_set_uint64_r(config_map, path, ull)) != CS_OK) {
goto icmap_set_error;
}
add_as_string = 0;
}
if (strcmp(path, "totem.ip_version") == 0) {
if ((strcmp(value, "ipv4") != 0) &&
(strcmp(value, "ipv6") != 0) &&
(strcmp(value, "ipv6-4") != 0) &&
(strcmp(value, "ipv4-6") != 0)) {
*error_string = "Invalid ip_version type";
return (0);
}
}
if (strcmp(path, "totem.crypto_model") == 0) {
if (handle_crypto_model(value, error_string) != 0) {
return (0);
}
}
if (strcmp(path, "totem.crypto_cipher") == 0) {
if ((strcmp(value, "none") != 0) &&
(strcmp(value, "aes256") != 0) &&
(strcmp(value, "aes192") != 0) &&
(strcmp(value, "aes128") != 0)) {
*error_string = "Invalid cipher type. "
"Should be none, aes256, aes192 or aes128";
return (0);
}
}
if (strcmp(path, "totem.crypto_hash") == 0) {
if ((strcmp(value, "none") != 0) &&
(strcmp(value, "md5") != 0) &&
(strcmp(value, "sha1") != 0) &&
(strcmp(value, "sha256") != 0) &&
(strcmp(value, "sha384") != 0) &&
(strcmp(value, "sha512") != 0)) {
*error_string = "Invalid hash type. "
"Should be none, md5, sha1, sha256, sha384 or sha512";
return (0);
}
}
if (strcmp(path, "totem.knet_compression_model") == 0) {
if (handle_compress_model(value, error_string) != 0) {
return (0);
}
}
break;
case MAIN_CP_CB_DATA_STATE_SYSTEM:
if (strcmp(path, "system.qb_ipc_type") == 0) {
if ((strcmp(value, "native") != 0) &&
(strcmp(value, "shm") != 0) &&
(strcmp(value, "socket") != 0)) {
*error_string = "Invalid system.qb_ipc_type";
return (0);
}
}
if (strcmp(path, "system.sched_rr") == 0) {
if ((strcmp(value, "yes") != 0) &&
(strcmp(value, "no") != 0)) {
*error_string = "Invalid system.sched_rr value";
return (0);
}
}
if (strcmp(path, "system.move_to_root_cgroup") == 0) {
if ((strcmp(value, "yes") != 0) &&
(strcmp(value, "no") != 0) &&
(strcmp(value, "auto") != 0)) {
*error_string = "Invalid system.move_to_root_cgroup";
return (0);
}
}
if (strcmp(path, "system.allow_knet_handle_fallback") == 0) {
if ((strcmp(value, "yes") != 0) &&
(strcmp(value, "no") != 0)) {
*error_string = "Invalid system.allow_knet_handle_fallback";
return (0);
}
}
break;
case MAIN_CP_CB_DATA_STATE_INTERFACE:
if (strcmp(path, "totem.interface.linknumber") == 0) {
val_type = ICMAP_VALUETYPE_UINT8;
if (safe_atoq(value, &val, val_type) != 0) {
goto atoi_error;
}
data->linknumber = val;
add_as_string = 0;
}
if (strcmp(path, "totem.interface.bindnetaddr") == 0) {
data->bindnetaddr = strdup(value);
add_as_string = 0;
}
if (strcmp(path, "totem.interface.mcastaddr") == 0) {
data->mcastaddr = strdup(value);
add_as_string = 0;
}
if (strcmp(path, "totem.interface.broadcast") == 0) {
data->broadcast = strdup(value);
add_as_string = 0;
}
if (strcmp(path, "totem.interface.mcastport") == 0) {
val_type = ICMAP_VALUETYPE_UINT16;
if (safe_atoq(value, &val, val_type) != 0) {
goto atoi_error;
}
data->mcastport = val;
add_as_string = 0;
}
if (strcmp(path, "totem.interface.ttl") == 0) {
val_type = ICMAP_VALUETYPE_UINT8;
if (safe_atoq(value, &val, val_type) != 0) {
goto atoi_error;
}
data->ttl = val;
add_as_string = 0;
}
if (strcmp(path, "totem.interface.knet_link_priority") == 0) {
val_type = ICMAP_VALUETYPE_UINT8;
if (safe_atoq(value, &val, val_type) != 0) {
goto atoi_error;
}
data->knet_link_priority = val;
add_as_string = 0;
}
if (strcmp(path, "totem.interface.knet_ping_interval") == 0) {
val_type = ICMAP_VALUETYPE_UINT32;
if (safe_atoq(value, &val, val_type) != 0) {
goto atoi_error;
}
data->knet_ping_interval = val;
add_as_string = 0;
}
if (strcmp(path, "totem.interface.knet_ping_timeout") == 0) {
val_type = ICMAP_VALUETYPE_UINT32;
if (safe_atoq(value, &val, val_type) != 0) {
goto atoi_error;
}
data->knet_ping_timeout = val;
add_as_string = 0;
}
if (strcmp(path, "totem.interface.knet_ping_precision") == 0) {
val_type = ICMAP_VALUETYPE_UINT32;
if (safe_atoq(value, &val, val_type) != 0) {
goto atoi_error;
}
data->knet_ping_precision = val;
add_as_string = 0;
}
if (strcmp(path, "totem.interface.knet_pong_count") == 0) {
val_type = ICMAP_VALUETYPE_UINT32;
if (safe_atoq(value, &val, val_type) != 0) {
goto atoi_error;
}
data->knet_pong_count = val;
add_as_string = 0;
}
if (strcmp(path, "totem.interface.knet_transport") == 0) {
val_type = ICMAP_VALUETYPE_STRING;
data->knet_transport = strdup(value);
add_as_string = 0;
}
break;
case MAIN_CP_CB_DATA_STATE_LOGGER_SUBSYS:
if (strcmp(key, "subsys") == 0) {
data->subsys = strdup(value);
if (data->subsys == NULL) {
*error_string = "Can't alloc memory";
return (0);
}
} else {
kv_item = malloc(sizeof(*kv_item));
if (kv_item == NULL) {
*error_string = "Can't alloc memory";
return (0);
}
memset(kv_item, 0, sizeof(*kv_item));
kv_item->key = strdup(key);
kv_item->value = strdup(value);
if (kv_item->key == NULL || kv_item->value == NULL) {
free(kv_item->key);
free(kv_item->value);
free(kv_item);
*error_string = "Can't alloc memory";
return (0);
}
qb_list_init(&kv_item->list);
qb_list_add(&kv_item->list, &data->logger_subsys_items_head);
}
add_as_string = 0;
break;
case MAIN_CP_CB_DATA_STATE_LOGGING_DAEMON:
if (strcmp(key, "subsys") == 0) {
data->subsys = strdup(value);
if (data->subsys == NULL) {
*error_string = "Can't alloc memory";
return (0);
}
} else if (strcmp(key, "name") == 0) {
data->logging_daemon_name = strdup(value);
if (data->logging_daemon_name == NULL) {
*error_string = "Can't alloc memory";
return (0);
}
} else {
kv_item = malloc(sizeof(*kv_item));
if (kv_item == NULL) {
*error_string = "Can't alloc memory";
return (0);
}
memset(kv_item, 0, sizeof(*kv_item));
kv_item->key = strdup(key);
kv_item->value = strdup(value);
if (kv_item->key == NULL || kv_item->value == NULL) {
free(kv_item->key);
free(kv_item->value);
free(kv_item);
*error_string = "Can't alloc memory";
return (0);
}
qb_list_init(&kv_item->list);
qb_list_add(&kv_item->list, &data->logger_subsys_items_head);
}
add_as_string = 0;
break;
case MAIN_CP_CB_DATA_STATE_UIDGID:
if (strcmp(key, "uid") == 0) {
uid = uid_determine(value);
if (uid == -1) {
*error_string = error_string_response;
return (0);
}
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.uid.%u",
uid);
if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
goto icmap_set_error;
}
add_as_string = 0;
} else if (strcmp(key, "gid") == 0) {
gid = gid_determine(value);
if (gid == -1) {
*error_string = error_string_response;
return (0);
}
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.gid.%u",
gid);
if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
goto icmap_set_error;
}
add_as_string = 0;
} else {
*error_string = "uidgid: Only uid and gid are allowed items";
return (0);
}
break;
case MAIN_CP_CB_DATA_STATE_MEMBER:
if (strcmp(key, "memberaddr") != 0) {
*error_string = "Only memberaddr is allowed in member section";
return (0);
}
kv_item = malloc(sizeof(*kv_item));
if (kv_item == NULL) {
*error_string = "Can't alloc memory";
return (0);
}
memset(kv_item, 0, sizeof(*kv_item));
kv_item->key = strdup(key);
kv_item->value = strdup(value);
if (kv_item->key == NULL || kv_item->value == NULL) {
free(kv_item->key);
free(kv_item->value);
free(kv_item);
*error_string = "Can't alloc memory";
return (0);
}
qb_list_init(&kv_item->list);
qb_list_add(&kv_item->list, &data->member_items_head);
add_as_string = 0;
break;
case MAIN_CP_CB_DATA_STATE_NODELIST:
break;
case MAIN_CP_CB_DATA_STATE_NODELIST_NODE:
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "nodelist.node.%u.%s", data->node_number, key);
if ((strcmp(key, "nodeid") == 0) ||
(strcmp(key, "quorum_votes") == 0)) {
val_type = ICMAP_VALUETYPE_UINT32;
if (safe_atoq(value, &val, val_type) != 0) {
goto atoi_error;
}
if ((cs_err = icmap_set_uint32_r(config_map, key_name, val)) != CS_OK) {
goto icmap_set_error;
}
add_as_string = 0;
}
if (add_as_string) {
if ((cs_err = icmap_set_string_r(config_map, key_name, value)) != CS_OK) {
goto icmap_set_error;
};
add_as_string = 0;
}
break;
case MAIN_CP_CB_DATA_STATE_RESOURCES:
if (strcmp(key, "watchdog_timeout") == 0) {
val_type = ICMAP_VALUETYPE_UINT32;
if (safe_atoq(value, &val, val_type) != 0) {
goto atoi_error;
}
if ((cs_err = icmap_set_uint32_r(config_map,path, val)) != CS_OK) {
goto icmap_set_error;
}
add_as_string = 0;
}
break;
case MAIN_CP_CB_DATA_STATE_RESOURCES_SYSTEM:
case MAIN_CP_CB_DATA_STATE_RESOURCES_SYSTEM_MEMUSED:
if (strcmp(key, "poll_period") == 0) {
if (str_to_ull(value, &ull) != 0) {
goto atoi_error;
}
if ((cs_err = icmap_set_uint64_r(config_map,path, ull)) != CS_OK) {
goto icmap_set_error;
}
add_as_string = 0;
}
break;
case MAIN_CP_CB_DATA_STATE_RESOURCES_PROCESS:
case MAIN_CP_CB_DATA_STATE_RESOURCES_PROCESS_MEMUSED:
if (strcmp(key, "poll_period") == 0) {
if (str_to_ull(value, &ull) != 0) {
goto atoi_error;
}
if ((cs_err = icmap_set_uint64_r(config_map,path, ull)) != CS_OK) {
goto icmap_set_error;
}
add_as_string = 0;
}
break;
}
if (add_as_string) {
if ((cs_err = icmap_set_string_r(config_map, path, value)) != CS_OK) {
goto icmap_set_error;
}
}
break;
case PARSER_CB_SECTION_START:
if (strcmp(path, "totem.interface") == 0) {
*state = MAIN_CP_CB_DATA_STATE_INTERFACE;
data->linknumber = 0;
data->mcastport = -1;
data->ttl = -1;
data->knet_link_priority = -1;
data->knet_ping_interval = -1;
data->knet_ping_timeout = -1;
data->knet_ping_precision = -1;
data->knet_pong_count = -1;
data->knet_transport = NULL;
qb_list_init(&data->member_items_head);
};
if (strcmp(path, "totem") == 0) {
*state = MAIN_CP_CB_DATA_STATE_TOTEM;
};
if (strcmp(path, "system") == 0) {
*state = MAIN_CP_CB_DATA_STATE_SYSTEM;
}
if (strcmp(path, "logging.logger_subsys") == 0) {
*state = MAIN_CP_CB_DATA_STATE_LOGGER_SUBSYS;
qb_list_init(&data->logger_subsys_items_head);
data->subsys = NULL;
}
if (strcmp(path, "logging.logging_daemon") == 0) {
*state = MAIN_CP_CB_DATA_STATE_LOGGING_DAEMON;
qb_list_init(&data->logger_subsys_items_head);
data->subsys = NULL;
data->logging_daemon_name = NULL;
}
if (strcmp(path, "uidgid") == 0) {
*state = MAIN_CP_CB_DATA_STATE_UIDGID;
}
if (strcmp(path, "totem.interface.member") == 0) {
*state = MAIN_CP_CB_DATA_STATE_MEMBER;
}
if (strcmp(path, "quorum") == 0) {
*state = MAIN_CP_CB_DATA_STATE_QUORUM;
}
if (strcmp(path, "quorum.device") == 0) {
*state = MAIN_CP_CB_DATA_STATE_QDEVICE;
}
if (strcmp(path, "nodelist") == 0) {
*state = MAIN_CP_CB_DATA_STATE_NODELIST;
data->node_number = 0;
}
if (strcmp(path, "nodelist.node") == 0) {
*state = MAIN_CP_CB_DATA_STATE_NODELIST_NODE;
}
if (strcmp(path, "resources") == 0) {
*state = MAIN_CP_CB_DATA_STATE_RESOURCES;
}
if (strcmp(path, "resources.system") == 0) {
*state = MAIN_CP_CB_DATA_STATE_RESOURCES_SYSTEM;
}
if (strcmp(path, "resources.system.memory_used") == 0) {
*state = MAIN_CP_CB_DATA_STATE_RESOURCES_SYSTEM_MEMUSED;
}
if (strcmp(path, "resources.process") == 0) {
*state = MAIN_CP_CB_DATA_STATE_RESOURCES_PROCESS;
}
if (strcmp(path, "resources.process.memory_used") == 0) {
*state = MAIN_CP_CB_DATA_STATE_RESOURCES_PROCESS_MEMUSED;
}
break;
case PARSER_CB_SECTION_END:
switch (*state) {
case MAIN_CP_CB_DATA_STATE_INTERFACE:
/*
* Create new interface section
*/
if (data->bindnetaddr != NULL) {
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.bindnetaddr",
data->linknumber);
cs_err = icmap_set_string_r(config_map, key_name, data->bindnetaddr);
free(data->bindnetaddr);
data->bindnetaddr = NULL;
if (cs_err != CS_OK) {
goto icmap_set_error;
}
}
if (data->mcastaddr != NULL) {
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastaddr",
data->linknumber);
cs_err = icmap_set_string_r(config_map, key_name, data->mcastaddr);
free(data->mcastaddr);
data->mcastaddr = NULL;
if (cs_err != CS_OK) {
goto icmap_set_error;
}
}
if (data->broadcast != NULL) {
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.broadcast",
data->linknumber);
cs_err = icmap_set_string_r(config_map, key_name, data->broadcast);
free(data->broadcast);
data->broadcast = NULL;
if (cs_err != CS_OK) {
goto icmap_set_error;
}
}
if (data->mcastport > -1) {
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.mcastport",
data->linknumber);
if ((cs_err = icmap_set_uint16_r(config_map, key_name,
data->mcastport)) != CS_OK) {
goto icmap_set_error;
}
}
if (data->ttl > -1) {
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.ttl",
data->linknumber);
if ((cs_err = icmap_set_uint8_r(config_map, key_name, data->ttl)) != CS_OK) {
goto icmap_set_error;
}
}
if (data->knet_link_priority > -1) {
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_link_priority",
data->linknumber);
if ((cs_err = icmap_set_uint8_r(config_map, key_name,
data->knet_link_priority)) != CS_OK) {
goto icmap_set_error;
}
}
if (data->knet_ping_interval > -1) {
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_interval",
data->linknumber);
if ((cs_err = icmap_set_uint32_r(config_map, key_name,
data->knet_ping_interval)) != CS_OK) {
goto icmap_set_error;
}
}
if (data->knet_ping_timeout > -1) {
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_timeout",
data->linknumber);
if ((cs_err = icmap_set_uint32_r(config_map, key_name,
data->knet_ping_timeout)) != CS_OK) {
goto icmap_set_error;
}
}
if (data->knet_ping_precision > -1) {
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_ping_precision",
data->linknumber);
if ((cs_err = icmap_set_uint32_r(config_map, key_name,
data->knet_ping_precision)) != CS_OK) {
goto icmap_set_error;
}
}
if (data->knet_pong_count > -1) {
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_pong_count",
data->linknumber);
if ((cs_err = icmap_set_uint32_r(config_map, key_name,
data->knet_pong_count)) != CS_OK) {
goto icmap_set_error;
}
}
if (data->knet_transport) {
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.knet_transport",
data->linknumber);
cs_err = icmap_set_string_r(config_map, key_name, data->knet_transport);
free(data->knet_transport);
if (cs_err != CS_OK) {
goto icmap_set_error;
}
}
ii = 0;
qb_list_for_each_safe(iter, tmp_iter, &(data->member_items_head)) {
kv_item = qb_list_entry(iter, struct key_value_list_item, list);
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "totem.interface.%u.member.%u",
data->linknumber, ii);
cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
free(kv_item->value);
free(kv_item->key);
free(kv_item);
ii++;
if (cs_err != CS_OK) {
goto icmap_set_error;
}
}
break;
case MAIN_CP_CB_DATA_STATE_LOGGER_SUBSYS:
if (data->subsys == NULL) {
*error_string = "No subsys key in logger_subsys directive";
return (0);
}
qb_list_for_each_safe(iter, tmp_iter, &(data->logger_subsys_items_head)) {
kv_item = qb_list_entry(iter, struct key_value_list_item, list);
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.%s",
data->subsys, kv_item->key);
cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
free(kv_item->value);
free(kv_item->key);
free(kv_item);
if (cs_err != CS_OK) {
goto icmap_set_error;
}
}
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
data->subsys);
cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
free(data->subsys);
if (cs_err != CS_OK) {
goto icmap_set_error;
}
break;
case MAIN_CP_CB_DATA_STATE_LOGGING_DAEMON:
if (data->logging_daemon_name == NULL) {
*error_string = "No name key in logging_daemon directive";
return (0);
}
qb_list_for_each_safe(iter, tmp_iter, &(data->logger_subsys_items_head)) {
kv_item = qb_list_entry(iter, struct key_value_list_item, list);
if (data->subsys == NULL) {
if (strcmp(data->logging_daemon_name, "corosync") == 0) {
snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
"logging.%s",
kv_item->key);
} else {
snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
"logging.logging_daemon.%s.%s",
data->logging_daemon_name, kv_item->key);
}
} else {
if (strcmp(data->logging_daemon_name, "corosync") == 0) {
snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
"logging.logger_subsys.%s.%s",
data->subsys,
kv_item->key);
} else {
snprintf(key_name, ICMAP_KEYNAME_MAXLEN,
"logging.logging_daemon.%s.%s.%s",
data->logging_daemon_name, data->subsys,
kv_item->key);
}
}
cs_err = icmap_set_string_r(config_map, key_name, kv_item->value);
free(kv_item->value);
free(kv_item->key);
free(kv_item);
if (cs_err != CS_OK) {
goto icmap_set_error;
}
}
if (data->subsys == NULL) {
if (strcmp(data->logging_daemon_name, "corosync") != 0) {
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.name",
data->logging_daemon_name);
cs_err = icmap_set_string_r(config_map, key_name, data->logging_daemon_name);
}
} else {
if (strcmp(data->logging_daemon_name, "corosync") == 0) {
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logger_subsys.%s.subsys",
data->subsys);
cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
} else {
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.subsys",
data->logging_daemon_name, data->subsys);
cs_err = icmap_set_string_r(config_map, key_name, data->subsys);
if (cs_err != CS_OK) {
free(data->subsys);
free(data->logging_daemon_name);
goto icmap_set_error;
}
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "logging.logging_daemon.%s.%s.name",
data->logging_daemon_name, data->subsys);
cs_err = icmap_set_string_r(config_map, key_name, data->logging_daemon_name);
}
}
free(data->subsys);
free(data->logging_daemon_name);
if (cs_err != CS_OK) {
goto icmap_set_error;
}
break;
case MAIN_CP_CB_DATA_STATE_NODELIST_NODE:
data->node_number++;
break;
case MAIN_CP_CB_DATA_STATE_NORMAL:
case MAIN_CP_CB_DATA_STATE_PLOAD:
case MAIN_CP_CB_DATA_STATE_UIDGID:
case MAIN_CP_CB_DATA_STATE_MEMBER:
case MAIN_CP_CB_DATA_STATE_QUORUM:
case MAIN_CP_CB_DATA_STATE_QDEVICE:
case MAIN_CP_CB_DATA_STATE_NODELIST:
case MAIN_CP_CB_DATA_STATE_TOTEM:
case MAIN_CP_CB_DATA_STATE_SYSTEM:
break;
case MAIN_CP_CB_DATA_STATE_RESOURCES:
*state = MAIN_CP_CB_DATA_STATE_NORMAL;
break;
case MAIN_CP_CB_DATA_STATE_RESOURCES_SYSTEM:
*state = MAIN_CP_CB_DATA_STATE_RESOURCES;
break;
case MAIN_CP_CB_DATA_STATE_RESOURCES_SYSTEM_MEMUSED:
*state = MAIN_CP_CB_DATA_STATE_RESOURCES_SYSTEM;
break;
case MAIN_CP_CB_DATA_STATE_RESOURCES_PROCESS:
*state = MAIN_CP_CB_DATA_STATE_RESOURCES;
break;
case MAIN_CP_CB_DATA_STATE_RESOURCES_PROCESS_MEMUSED:
*state = MAIN_CP_CB_DATA_STATE_RESOURCES_PROCESS;
break;
}
break;
}
return (1);
atoi_error:
min_val = max_val = 0;
/*
* This is really assert, because developer ether doesn't set val_type correctly or
* we've got here after some nasty memory overwrite
*/
assert(safe_atoq_range(val_type, &min_val, &max_val) == 0);
if (snprintf(formated_err, sizeof(formated_err),
"Value of key \"%s\" is expected to be integer in range (%lld..%lld), but \"%s\" was given",
key_name, min_val, max_val, value) >= sizeof(formated_err)) {
*error_string = "Can't format parser error message";
} else {
*error_string = formated_err;
}
return (0);
icmap_set_error:
if (snprintf(formated_err, sizeof(formated_err),
"Can't store key \"%s\" into icmap, returned error is %s",
key_name, cs_strerror(cs_err)) >= sizeof(formated_err)) {
*error_string = "Can't format parser error message";
} else {
*error_string = formated_err;
}
return (0);
}
static int uidgid_config_parser_cb(const char *path,
char *key,
char *value,
enum main_cp_cb_data_state *state,
enum parser_cb_type type,
const char **error_string,
icmap_map_t config_map,
void *user_data)
{
char key_name[ICMAP_KEYNAME_MAXLEN];
int uid, gid;
static char formated_err[256];
cs_error_t cs_err;
switch (type) {
case PARSER_CB_START:
break;
case PARSER_CB_END:
break;
case PARSER_CB_ITEM:
if (strcmp(path, "uidgid.uid") == 0) {
uid = uid_determine(value);
if (uid == -1) {
*error_string = error_string_response;
return (0);
}
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.uid.%u",
uid);
if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
goto icmap_set_error;
}
} else if (strcmp(path, "uidgid.gid") == 0) {
gid = gid_determine(value);
if (gid == -1) {
*error_string = error_string_response;
return (0);
}
snprintf(key_name, ICMAP_KEYNAME_MAXLEN, "uidgid.config.gid.%u",
gid);
if ((cs_err = icmap_set_uint8_r(config_map, key_name, 1)) != CS_OK) {
goto icmap_set_error;
}
} else {
*error_string = "uidgid: Only uid and gid are allowed items";
return (0);
}
break;
case PARSER_CB_SECTION_START:
if (strcmp(path, "uidgid") != 0) {
*error_string = "uidgid: Can't add subsection different than uidgid";
return (0);
};
break;
case PARSER_CB_SECTION_END:
break;
}
return (1);
icmap_set_error:
if (snprintf(formated_err, sizeof(formated_err),
"Can't store key \"%s\" into icmap, returned error is %s",
key_name, cs_strerror(cs_err)) >= sizeof(formated_err)) {
*error_string = "Can't format parser error message";
} else {
*error_string = formated_err;
}
return (0);
}
static int read_uidgid_files_into_icmap(
const char **error_string,
icmap_map_t config_map)
{
FILE *fp;
char *dirname_res;
DIR *dp;
struct dirent *dirent;
char filename[PATH_MAX + FILENAME_MAX + 1];
char uidgid_dirname[PATH_MAX + FILENAME_MAX + 1];
int res = 0;
struct stat stat_buf;
enum main_cp_cb_data_state state = MAIN_CP_CB_DATA_STATE_NORMAL;
char key_name[ICMAP_KEYNAME_MAXLEN];
int line_no;
/*
* Build uidgid directory based on corosync.conf file location
*/
res = snprintf(filename, sizeof(filename), "%s",
corosync_get_config_file());
if (res >= sizeof(filename)) {
*error_string = "uidgid.d path too long";
return (-1);
}
dirname_res = dirname(filename);
res = snprintf(uidgid_dirname, sizeof(uidgid_dirname), "%s/%s",
dirname_res, "uidgid.d");
if (res >= sizeof(uidgid_dirname)) {
*error_string = "uidgid.d path too long";
return (-1);
}
dp = opendir (uidgid_dirname);
if (dp == NULL)
return 0;
for (dirent = readdir(dp);
dirent != NULL;
dirent = readdir(dp)) {
res = snprintf(filename, sizeof (filename), "%s/%s", uidgid_dirname, dirent->d_name);
if (res >= sizeof(filename)) {
res = -1;
*error_string = "uidgid.d dirname path too long";
goto error_exit;
}
res = stat (filename, &stat_buf);
if (res == 0 && S_ISREG(stat_buf.st_mode)) {
fp = fopen (filename, "r");
if (fp == NULL) continue;
key_name[0] = 0;
line_no = 0;
res = parse_section(fp, filename, &line_no, key_name, error_string, 0, state,
uidgid_config_parser_cb, config_map, NULL);
fclose (fp);
if (res != 0) {
goto error_exit;
}
}
}
error_exit:
closedir(dp);
return res;
}
/* Read config file and load into icmap */
static int read_config_file_into_icmap(
const char **error_string,
icmap_map_t config_map)
{
FILE *fp;
const char *filename;
char *error_reason = error_string_response;
int res;
char key_name[ICMAP_KEYNAME_MAXLEN];
struct main_cp_cb_data data;
enum main_cp_cb_data_state state = MAIN_CP_CB_DATA_STATE_NORMAL;
int line_no;
filename = corosync_get_config_file();
fp = fopen (filename, "r");
if (fp == NULL) {
char error_str[100];
const char *error_ptr = qb_strerror_r(errno, error_str, sizeof(error_str));
snprintf (error_reason, sizeof(error_string_response),
"Can't read file %s: %s",
filename, error_ptr);
*error_string = error_reason;
return -1;
}
key_name[0] = 0;
line_no = 0;
res = parse_section(fp, filename, &line_no, key_name, error_string, 0, state,
main_config_parser_cb, config_map, &data);
fclose(fp);
if (res == 0) {
res = read_uidgid_files_into_icmap(error_string, config_map);
}
if (res == 0) {
snprintf (error_reason, sizeof(error_string_response),
"Successfully read main configuration file '%s'.", filename);
*error_string = error_reason;
}
return res;
}
diff --git a/exec/icmap.c b/exec/icmap.c
index cdc66180..e1270849 100644
--- a/exec/icmap.c
+++ b/exec/icmap.c
@@ -1,1334 +1,1337 @@
/*
* Copyright (c) 2011 Red Hat, Inc.
*
* All rights reserved.
*
* Author: Jan Friesse (jfriesse@redhat.com)
*
* This software licensed under BSD license, the text of which follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the Red Hat, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <config.h>
#include <string.h>
#include <stdio.h>
#include <corosync/corotypes.h>
#include <qb/qbdefs.h>
#include <qb/qblist.h>
#include <corosync/icmap.h>
#define ICMAP_MAX_VALUE_LEN (16*1024)
struct icmap_item {
char *key_name;
icmap_value_types_t type;
size_t value_len;
char value[];
};
struct icmap_map {
qb_map_t *qb_map;
};
static icmap_map_t icmap_global_map;
struct icmap_track {
char *key_name;
int32_t track_type;
icmap_notify_fn_t notify_fn;
void *user_data;
struct qb_list_head list;
};
struct icmap_ro_access_item {
char *key_name;
int prefix;
struct qb_list_head list;
};
QB_LIST_DECLARE (icmap_ro_access_item_list_head);
QB_LIST_DECLARE (icmap_track_list_head);
/*
* Static functions declarations
*/
/*
* Check if key_name is valid icmap key name. Returns 0 on success, and -1 on fail
*/
static int icmap_check_key_name(const char *key_name);
/*
* Check that value with given type has correct length value_len. Returns 0 on success,
* and -1 on fail
*/
static int icmap_check_value_len(const void *value, size_t value_len, icmap_value_types_t type);
/*
* Checks if item has same value as value with value_len and given type. Returns 0 if not, otherwise !0.
*/
static int icmap_item_eq(const struct icmap_item *item, const void *value, size_t value_len, icmap_value_types_t type);
/*
* Checks if given character is valid in key name. Returns 0 if not, otherwise !0.
*/
static int icmap_is_valid_name_char(char c);
/*
* Helper for getting integer and float value with given type for key key_name and store it in value.
*/
static cs_error_t icmap_get_int_r(
const icmap_map_t map,
const char *key_name,
void *value,
icmap_value_types_t type);
/*
* Return raw item value data. Internal function used by icmap_get_r which does most
* of arguments validity checks but doesn't copy data (it returns raw item data
* pointer). It's not very safe tho it's static.
*/
static cs_error_t icmap_get_ref_r(
const icmap_map_t map,
const char *key_name,
void **value,
size_t *value_len,
icmap_value_types_t *type);
/*
* Function implementation
*/
int32_t icmap_tt_to_qbtt(int32_t track_type)
{
int32_t res = 0;
if (track_type & ICMAP_TRACK_DELETE) {
res |= QB_MAP_NOTIFY_DELETED;
}
if (track_type & ICMAP_TRACK_MODIFY) {
res |= QB_MAP_NOTIFY_REPLACED;
}
if (track_type & ICMAP_TRACK_ADD) {
res |= QB_MAP_NOTIFY_INSERTED;
}
if (track_type & ICMAP_TRACK_PREFIX) {
res |= QB_MAP_NOTIFY_RECURSIVE;
}
return (res);
}
int32_t icmap_qbtt_to_tt(int32_t track_type)
{
int32_t res = 0;
if (track_type & QB_MAP_NOTIFY_DELETED) {
res |= ICMAP_TRACK_DELETE;
}
if (track_type & QB_MAP_NOTIFY_REPLACED) {
res |= ICMAP_TRACK_MODIFY;
}
if (track_type & QB_MAP_NOTIFY_INSERTED) {
res |= ICMAP_TRACK_ADD;
}
if (track_type & QB_MAP_NOTIFY_RECURSIVE) {
res |= ICMAP_TRACK_PREFIX;
}
return (res);
}
static void icmap_map_free_cb(uint32_t event,
char* key, void* old_value,
void* value, void* user_data)
{
struct icmap_item *item = (struct icmap_item *)old_value;
/*
* value == old_value -> fast_adjust_int was used, don't free data
*/
if (item != NULL && value != old_value) {
free(item->key_name);
free(item);
}
}
cs_error_t icmap_init_r(icmap_map_t *result)
{
int32_t err;
*result = malloc(sizeof(struct icmap_map));
if (*result == NULL) {
return (CS_ERR_NO_MEMORY);
}
(*result)->qb_map = qb_trie_create();
if ((*result)->qb_map == NULL) {
free(*result);
return (CS_ERR_INIT);
}
err = qb_map_notify_add((*result)->qb_map, NULL, icmap_map_free_cb, QB_MAP_NOTIFY_FREE, NULL);
if (err != 0) {
qb_map_destroy((*result)->qb_map);
free(*result);
}
return (qb_to_cs_error(err));
}
cs_error_t icmap_init(void)
{
return (icmap_init_r(&icmap_global_map));
}
static void icmap_set_ro_access_free(void)
{
struct qb_list_head *iter, *tmp_iter;
struct icmap_ro_access_item *icmap_ro_ai;
qb_list_for_each_safe(iter, tmp_iter, &icmap_ro_access_item_list_head) {
icmap_ro_ai = qb_list_entry(iter, struct icmap_ro_access_item, list);
qb_list_del(&icmap_ro_ai->list);
free(icmap_ro_ai->key_name);
free(icmap_ro_ai);
}
}
static void icmap_del_all_track(void)
{
struct qb_list_head *iter, *tmp_iter;
struct icmap_track *icmap_track;
qb_list_for_each_safe(iter, tmp_iter, &icmap_track_list_head) {
icmap_track = qb_list_entry(iter, struct icmap_track, list);
icmap_track_delete(icmap_track);
}
}
void icmap_fini_r(const icmap_map_t map)
{
qb_map_destroy(map->qb_map);
free(map);
return;
}
void icmap_fini(void)
{
icmap_del_all_track();
/*
* catch 22 warning:
* We need to drop this notify but we can't because it calls icmap_map_free_cb
* while destroying the tree to free icmap_item(s).
* -> qb_map_notify_del_2(icmap_map, NULL, icmap_map_free_cb, QB_MAP_NOTIFY_FREE, NULL);
* and we cannot call it after map_destroy. joy! :)
*/
icmap_fini_r(icmap_global_map);
icmap_set_ro_access_free();
return ;
}
icmap_map_t icmap_get_global_map(void)
{
return (icmap_global_map);
}
static int icmap_is_valid_name_char(char c)
{
return ((c >= 'a' && c <= 'z') ||
(c >= 'A' && c <= 'Z') ||
(c >= '0' && c <= '9') ||
c == '.' || c == '_' || c == '-' || c == '/' || c == ':');
}
void icmap_convert_name_to_valid_name(char *key_name)
{
int i;
for (i = 0; i < strlen(key_name); i++) {
if (!icmap_is_valid_name_char(key_name[i])) {
key_name[i] = '_';
}
}
}
static int icmap_check_key_name(const char *key_name)
{
int i;
if ((strlen(key_name) < ICMAP_KEYNAME_MINLEN) || strlen(key_name) > ICMAP_KEYNAME_MAXLEN) {
return (-1);
}
for (i = 0; i < strlen(key_name); i++) {
if (!icmap_is_valid_name_char(key_name[i])) {
return (-1);
}
}
return (0);
}
size_t icmap_get_valuetype_len(icmap_value_types_t type)
{
size_t res = 0;
switch (type) {
case ICMAP_VALUETYPE_INT8: res = sizeof(int8_t); break;
case ICMAP_VALUETYPE_UINT8: res = sizeof(uint8_t); break;
case ICMAP_VALUETYPE_INT16: res = sizeof(int16_t); break;
case ICMAP_VALUETYPE_UINT16: res = sizeof(uint16_t); break;
case ICMAP_VALUETYPE_INT32: res = sizeof(int32_t); break;
case ICMAP_VALUETYPE_UINT32: res = sizeof(uint32_t); break;
case ICMAP_VALUETYPE_INT64: res = sizeof(int64_t); break;
case ICMAP_VALUETYPE_UINT64: res = sizeof(uint64_t); break;
case ICMAP_VALUETYPE_FLOAT: res = sizeof(float); break;
case ICMAP_VALUETYPE_DOUBLE: res = sizeof(double); break;
case ICMAP_VALUETYPE_STRING:
case ICMAP_VALUETYPE_BINARY:
+ case ICMAP_VALUETYPE_BOOLEAN:
res = 0;
break;
}
return (res);
}
static int icmap_check_value_len(const void *value, size_t value_len, icmap_value_types_t type)
{
if (value_len > ICMAP_MAX_VALUE_LEN) {
return (-1);
}
if (type != ICMAP_VALUETYPE_STRING && type != ICMAP_VALUETYPE_BINARY) {
if (icmap_get_valuetype_len(type) == value_len) {
return (0);
} else {
return (-1);
}
}
if (type == ICMAP_VALUETYPE_STRING) {
/*
* value_len can be shorter then real string length, but never
* longer (+ 1 is because of 0 at the end of string)
*/
if (value_len > strlen((const char *)value) + 1) {
return (-1);
} else {
return (0);
}
}
return (0);
}
static int icmap_item_eq(const struct icmap_item *item, const void *value, size_t value_len, icmap_value_types_t type)
{
size_t ptr_len;
if (item->type != type) {
return (0);
}
if (item->type == ICMAP_VALUETYPE_STRING) {
ptr_len = strlen((const char *)value);
if (ptr_len > value_len) {
ptr_len = value_len;
}
ptr_len++;
} else {
ptr_len = value_len;
}
if (item->value_len == ptr_len) {
return (memcmp(item->value, value, value_len) == 0);
};
return (0);
}
int icmap_key_value_eq(
const icmap_map_t map1,
const char *key_name1,
const icmap_map_t map2,
const char *key_name2)
{
struct icmap_item *item1, *item2;
if (map1 == NULL || key_name1 == NULL || map2 == NULL || key_name2 == NULL) {
return (0);
}
item1 = qb_map_get(map1->qb_map, key_name1);
item2 = qb_map_get(map2->qb_map, key_name2);
if (item1 == NULL || item2 == NULL) {
return (0);
}
return (icmap_item_eq(item1, item2->value, item2->value_len, item2->type));
}
cs_error_t icmap_set_r(
const icmap_map_t map,
const char *key_name,
const void *value,
size_t value_len,
icmap_value_types_t type)
{
struct icmap_item *item;
struct icmap_item *new_item;
size_t new_value_len;
size_t new_item_size;
if (value == NULL || key_name == NULL) {
return (CS_ERR_INVALID_PARAM);
}
if (icmap_check_value_len(value, value_len, type) != 0) {
return (CS_ERR_INVALID_PARAM);
}
item = qb_map_get(map->qb_map, key_name);
if (item != NULL) {
/*
* Check that key is really changed
*/
if (icmap_item_eq(item, value, value_len, type)) {
return (CS_OK);
}
} else {
if (icmap_check_key_name(key_name) != 0) {
return (CS_ERR_NAME_TOO_LONG);
}
}
if (type == ICMAP_VALUETYPE_BINARY || type == ICMAP_VALUETYPE_STRING) {
if (type == ICMAP_VALUETYPE_STRING) {
new_value_len = strlen((const char *)value);
if (new_value_len > value_len) {
new_value_len = value_len;
}
new_value_len++;
} else {
new_value_len = value_len;
}
} else {
new_value_len = icmap_get_valuetype_len(type);
}
new_item_size = sizeof(struct icmap_item) + new_value_len;
new_item = malloc(new_item_size);
if (new_item == NULL) {
return (CS_ERR_NO_MEMORY);
}
memset(new_item, 0, new_item_size);
if (item == NULL) {
new_item->key_name = strdup(key_name);
if (new_item->key_name == NULL) {
free(new_item);
return (CS_ERR_NO_MEMORY);
}
} else {
new_item->key_name = item->key_name;
item->key_name = NULL;
}
new_item->type = type;
new_item->value_len = new_value_len;
memcpy(new_item->value, value, new_value_len);
if (new_item->type == ICMAP_VALUETYPE_STRING) {
((char *)new_item->value)[new_value_len - 1] = 0;
}
qb_map_put(map->qb_map, new_item->key_name, new_item);
return (CS_OK);
}
cs_error_t icmap_set(
const char *key_name,
const void *value,
size_t value_len,
icmap_value_types_t type)
{
return (icmap_set_r(icmap_global_map, key_name, value, value_len, type));
}
cs_error_t icmap_set_int8_r(const icmap_map_t map, const char *key_name, int8_t value)
{
return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT8));
}
cs_error_t icmap_set_uint8_r(const icmap_map_t map, const char *key_name, uint8_t value)
{
return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT8));
}
cs_error_t icmap_set_int16_r(const icmap_map_t map, const char *key_name, int16_t value)
{
return (icmap_set_r(map,key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT16));
}
cs_error_t icmap_set_uint16_r(const icmap_map_t map, const char *key_name, uint16_t value)
{
return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT16));
}
cs_error_t icmap_set_int32_r(const icmap_map_t map, const char *key_name, int32_t value)
{
return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT32));
}
cs_error_t icmap_set_uint32_r(const icmap_map_t map, const char *key_name, uint32_t value)
{
return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT32));
}
cs_error_t icmap_set_int64_r(const icmap_map_t map, const char *key_name, int64_t value)
{
return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_INT64));
}
cs_error_t icmap_set_uint64_r(const icmap_map_t map, const char *key_name, uint64_t value)
{
return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_UINT64));
}
cs_error_t icmap_set_float_r(const icmap_map_t map, const char *key_name, float value)
{
return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_FLOAT));
}
cs_error_t icmap_set_double_r(const icmap_map_t map, const char *key_name, double value)
{
return (icmap_set_r(map, key_name, &value, sizeof(value), ICMAP_VALUETYPE_DOUBLE));
}
cs_error_t icmap_set_string_r(const icmap_map_t map, const char *key_name, const char *value)
{
if (value == NULL) {
return (CS_ERR_INVALID_PARAM);
}
return (icmap_set_r(map, key_name, value, strlen(value), ICMAP_VALUETYPE_STRING));
}
cs_error_t icmap_set_int8(const char *key_name, int8_t value)
{
return (icmap_set_int8_r(icmap_global_map, key_name, value));
}
cs_error_t icmap_set_uint8(const char *key_name, uint8_t value)
{
return (icmap_set_uint8_r(icmap_global_map, key_name, value));
}
cs_error_t icmap_set_int16(const char *key_name, int16_t value)
{
return (icmap_set_int16_r(icmap_global_map, key_name, value));
}
cs_error_t icmap_set_uint16(const char *key_name, uint16_t value)
{
return (icmap_set_uint16_r(icmap_global_map, key_name, value));
}
cs_error_t icmap_set_int32(const char *key_name, int32_t value)
{
return (icmap_set_int32_r(icmap_global_map, key_name, value));
}
cs_error_t icmap_set_uint32(const char *key_name, uint32_t value)
{
return (icmap_set_uint32_r(icmap_global_map, key_name, value));
}
cs_error_t icmap_set_int64(const char *key_name, int64_t value)
{
return (icmap_set_int64_r(icmap_global_map, key_name, value));
}
cs_error_t icmap_set_uint64(const char *key_name, uint64_t value)
{
return (icmap_set_uint64_r(icmap_global_map, key_name, value));
}
cs_error_t icmap_set_float(const char *key_name, float value)
{
return (icmap_set_float_r(icmap_global_map, key_name, value));
}
cs_error_t icmap_set_double(const char *key_name, double value)
{
return (icmap_set_double_r(icmap_global_map, key_name, value));
}
cs_error_t icmap_set_string(const char *key_name, const char *value)
{
return (icmap_set_string_r(icmap_global_map, key_name, value));
}
cs_error_t icmap_delete_r(const icmap_map_t map, const char *key_name)
{
struct icmap_item *item;
if (key_name == NULL) {
return (CS_ERR_INVALID_PARAM);
}
item = qb_map_get(map->qb_map, key_name);
if (item == NULL) {
return (CS_ERR_NOT_EXIST);
}
if (qb_map_rm(map->qb_map, item->key_name) != QB_TRUE) {
return (CS_ERR_NOT_EXIST);
}
return (CS_OK);
}
cs_error_t icmap_delete(const char *key_name)
{
return (icmap_delete_r(icmap_global_map, key_name));
}
static cs_error_t icmap_get_ref_r(
const icmap_map_t map,
const char *key_name,
void **value,
size_t *value_len,
icmap_value_types_t *type)
{
struct icmap_item *item;
if (key_name == NULL) {
return (CS_ERR_INVALID_PARAM);
}
item = qb_map_get(map->qb_map, key_name);
if (item == NULL) {
return (CS_ERR_NOT_EXIST);
}
if (type != NULL) {
*type = item->type;
}
if (value_len != NULL) {
*value_len = item->value_len;
}
if (value != NULL) {
*value = item->value;
}
return (CS_OK);
}
cs_error_t icmap_get_r(
const icmap_map_t map,
const char *key_name,
void *value,
size_t *value_len,
icmap_value_types_t *type)
{
cs_error_t res;
void *tmp_value;
size_t tmp_value_len;
res = icmap_get_ref_r(map, key_name, &tmp_value, &tmp_value_len, type);
if (res != CS_OK) {
return (res);
}
if (value == NULL) {
if (value_len != NULL) {
*value_len = tmp_value_len;
}
} else {
if (value_len == NULL || *value_len < tmp_value_len) {
return (CS_ERR_INVALID_PARAM);
}
*value_len = tmp_value_len;
memcpy(value, tmp_value, tmp_value_len);
}
return (CS_OK);
}
cs_error_t icmap_get(
const char *key_name,
void *value,
size_t *value_len,
icmap_value_types_t *type)
{
return (icmap_get_r(icmap_global_map, key_name, value, value_len, type));
}
cs_error_t icmap_get_string_r(icmap_map_t map, const char *key_name, char **str)
{
cs_error_t res;
size_t str_len;
icmap_value_types_t type;
res = icmap_get_r(map, key_name, NULL, &str_len, &type);
if (res != CS_OK || type != ICMAP_VALUETYPE_STRING) {
if (res == CS_OK) {
res = CS_ERR_INVALID_PARAM;
}
goto return_error;
}
*str = malloc(str_len);
if (*str == NULL) {
res = CS_ERR_NO_MEMORY;
goto return_error;
}
res = icmap_get_r(map, key_name, *str, &str_len, &type);
if (res != CS_OK) {
free(*str);
goto return_error;
}
return (CS_OK);
return_error:
return (res);
}
static cs_error_t icmap_get_int_r(
const icmap_map_t map,
const char *key_name,
void *value,
icmap_value_types_t type)
{
char key_value[16];
size_t key_size;
cs_error_t err;
icmap_value_types_t key_type;
key_size = sizeof(key_value);
memset(key_value, 0, key_size);
err = icmap_get_r(map, key_name, key_value, &key_size, &key_type);
if (err != CS_OK)
return (err);
if (key_type != type) {
return (CS_ERR_INVALID_PARAM);
}
memcpy(value, key_value, icmap_get_valuetype_len(key_type));
return (CS_OK);
}
cs_error_t icmap_get_int8_r(const icmap_map_t map, const char *key_name, int8_t *i8)
{
return (icmap_get_int_r(map, key_name, i8, ICMAP_VALUETYPE_INT8));
}
cs_error_t icmap_get_uint8_r(const icmap_map_t map, const char *key_name, uint8_t *u8)
{
return (icmap_get_int_r(map, key_name, u8, ICMAP_VALUETYPE_UINT8));
}
cs_error_t icmap_get_int16_r(const icmap_map_t map, const char *key_name, int16_t *i16)
{
return (icmap_get_int_r(map, key_name, i16, ICMAP_VALUETYPE_INT16));
}
cs_error_t icmap_get_uint16_r(const icmap_map_t map, const char *key_name, uint16_t *u16)
{
return (icmap_get_int_r(map, key_name, u16, ICMAP_VALUETYPE_UINT16));
}
cs_error_t icmap_get_int32_r(const icmap_map_t map, const char *key_name, int32_t *i32)
{
return (icmap_get_int_r(map, key_name, i32, ICMAP_VALUETYPE_INT32));
}
cs_error_t icmap_get_uint32_r(const icmap_map_t map, const char *key_name, uint32_t *u32)
{
return (icmap_get_int_r(map, key_name, u32, ICMAP_VALUETYPE_UINT32));
}
cs_error_t icmap_get_int64_r(const icmap_map_t map, const char *key_name, int64_t *i64)
{
return(icmap_get_int_r(map, key_name, i64, ICMAP_VALUETYPE_INT64));
}
cs_error_t icmap_get_uint64_r(const icmap_map_t map, const char *key_name, uint64_t *u64)
{
return (icmap_get_int_r(map, key_name, u64, ICMAP_VALUETYPE_UINT64));
}
cs_error_t icmap_get_float_r(const icmap_map_t map, const char *key_name, float *flt)
{
return (icmap_get_int_r(map, key_name, flt, ICMAP_VALUETYPE_FLOAT));
}
cs_error_t icmap_get_double_r(const icmap_map_t map, const char *key_name, double *dbl)
{
return (icmap_get_int_r(map, key_name, dbl, ICMAP_VALUETYPE_DOUBLE));
}
cs_error_t icmap_get_string(const char *key_name, char **str)
{
return (icmap_get_string_r(icmap_global_map, key_name, str));
}
cs_error_t icmap_get_int8(const char *key_name, int8_t *i8)
{
return (icmap_get_int8_r(icmap_global_map, key_name, i8));
}
cs_error_t icmap_get_uint8(const char *key_name, uint8_t *u8)
{
return (icmap_get_uint8_r(icmap_global_map, key_name, u8));
}
cs_error_t icmap_get_int16(const char *key_name, int16_t *i16)
{
return (icmap_get_int16_r(icmap_global_map, key_name, i16));
}
cs_error_t icmap_get_uint16(const char *key_name, uint16_t *u16)
{
return (icmap_get_uint16_r(icmap_global_map, key_name, u16));
}
cs_error_t icmap_get_int32(const char *key_name, int32_t *i32)
{
return (icmap_get_int32_r(icmap_global_map, key_name, i32));
}
cs_error_t icmap_get_uint32(const char *key_name, uint32_t *u32)
{
return (icmap_get_uint32_r(icmap_global_map, key_name, u32));
}
cs_error_t icmap_get_int64(const char *key_name, int64_t *i64)
{
return(icmap_get_int64_r(icmap_global_map, key_name, i64));
}
cs_error_t icmap_get_uint64(const char *key_name, uint64_t *u64)
{
return (icmap_get_uint64_r(icmap_global_map, key_name, u64));
}
cs_error_t icmap_get_float(const char *key_name, float *flt)
{
return (icmap_get_float_r(icmap_global_map, key_name, flt));
}
cs_error_t icmap_get_double(const char *key_name, double *dbl)
{
return (icmap_get_double_r(icmap_global_map, key_name, dbl));
}
cs_error_t icmap_adjust_int_r(
const icmap_map_t map,
const char *key_name,
int32_t step)
{
struct icmap_item *item;
uint8_t u8;
uint16_t u16;
uint32_t u32;
uint64_t u64;
cs_error_t err = CS_OK;
if (key_name == NULL) {
return (CS_ERR_INVALID_PARAM);
}
item = qb_map_get(map->qb_map, key_name);
if (item == NULL) {
return (CS_ERR_NOT_EXIST);
}
switch (item->type) {
case ICMAP_VALUETYPE_INT8:
case ICMAP_VALUETYPE_UINT8:
memcpy(&u8, item->value, sizeof(u8));
u8 += step;
err = icmap_set(key_name, &u8, sizeof(u8), item->type);
break;
case ICMAP_VALUETYPE_INT16:
case ICMAP_VALUETYPE_UINT16:
memcpy(&u16, item->value, sizeof(u16));
u16 += step;
err = icmap_set(key_name, &u16, sizeof(u16), item->type);
break;
case ICMAP_VALUETYPE_INT32:
case ICMAP_VALUETYPE_UINT32:
memcpy(&u32, item->value, sizeof(u32));
u32 += step;
err = icmap_set(key_name, &u32, sizeof(u32), item->type);
break;
case ICMAP_VALUETYPE_INT64:
case ICMAP_VALUETYPE_UINT64:
memcpy(&u64, item->value, sizeof(u64));
u64 += step;
err = icmap_set(key_name, &u64, sizeof(u64), item->type);
break;
case ICMAP_VALUETYPE_FLOAT:
case ICMAP_VALUETYPE_DOUBLE:
case ICMAP_VALUETYPE_STRING:
case ICMAP_VALUETYPE_BINARY:
+ case ICMAP_VALUETYPE_BOOLEAN:
err = CS_ERR_INVALID_PARAM;
break;
}
return (err);
}
cs_error_t icmap_adjust_int(
const char *key_name,
int32_t step)
{
return (icmap_adjust_int_r(icmap_global_map, key_name, step));
}
cs_error_t icmap_fast_adjust_int_r(
const icmap_map_t map,
const char *key_name,
int32_t step)
{
struct icmap_item *item;
cs_error_t err = CS_OK;
if (key_name == NULL) {
return (CS_ERR_INVALID_PARAM);
}
item = qb_map_get(map->qb_map, key_name);
if (item == NULL) {
return (CS_ERR_NOT_EXIST);
}
switch (item->type) {
case ICMAP_VALUETYPE_INT8:
case ICMAP_VALUETYPE_UINT8:
*(uint8_t *)item->value += step;
break;
case ICMAP_VALUETYPE_INT16:
case ICMAP_VALUETYPE_UINT16:
*(uint16_t *)item->value += step;
break;
case ICMAP_VALUETYPE_INT32:
case ICMAP_VALUETYPE_UINT32:
*(uint32_t *)item->value += step;
break;
case ICMAP_VALUETYPE_INT64:
case ICMAP_VALUETYPE_UINT64:
*(uint64_t *)item->value += step;
break;
case ICMAP_VALUETYPE_FLOAT:
case ICMAP_VALUETYPE_DOUBLE:
case ICMAP_VALUETYPE_STRING:
case ICMAP_VALUETYPE_BINARY:
+ case ICMAP_VALUETYPE_BOOLEAN:
err = CS_ERR_INVALID_PARAM;
break;
}
if (err == CS_OK) {
qb_map_put(map->qb_map, item->key_name, item);
}
return (err);
}
cs_error_t icmap_fast_adjust_int(
const char *key_name,
int32_t step)
{
return (icmap_fast_adjust_int_r(icmap_global_map, key_name, step));
}
cs_error_t icmap_inc_r(const icmap_map_t map, const char *key_name)
{
return (icmap_adjust_int_r(map, key_name, 1));
}
cs_error_t icmap_inc(const char *key_name)
{
return (icmap_inc_r(icmap_global_map, key_name));
}
cs_error_t icmap_dec_r(const icmap_map_t map, const char *key_name)
{
return (icmap_adjust_int_r(map, key_name, -1));
}
cs_error_t icmap_dec(const char *key_name)
{
return (icmap_dec_r(icmap_global_map, key_name));
}
cs_error_t icmap_fast_inc_r(const icmap_map_t map, const char *key_name)
{
return (icmap_fast_adjust_int_r(map, key_name, 1));
}
cs_error_t icmap_fast_inc(const char *key_name)
{
return (icmap_fast_inc_r(icmap_global_map, key_name));
}
cs_error_t icmap_fast_dec_r(const icmap_map_t map, const char *key_name)
{
return (icmap_fast_adjust_int_r(map, key_name, -1));
}
cs_error_t icmap_fast_dec(const char *key_name)
{
return (icmap_fast_dec_r(icmap_global_map, key_name));
}
icmap_iter_t icmap_iter_init_r(const icmap_map_t map, const char *prefix)
{
return (qb_map_pref_iter_create(map->qb_map, prefix));
}
icmap_iter_t icmap_iter_init(const char *prefix)
{
return (icmap_iter_init_r(icmap_global_map, prefix));
}
const char *icmap_iter_next(icmap_iter_t iter, size_t *value_len, icmap_value_types_t *type)
{
struct icmap_item *item;
const char *res;
res = qb_map_iter_next(iter, (void **)&item);
if (res == NULL) {
return (res);
}
if (value_len != NULL) {
*value_len = item->value_len;
}
if (type != NULL) {
*type = item->type;
}
return (res);
}
void icmap_iter_finalize(icmap_iter_t iter)
{
qb_map_iter_free(iter);
}
static void icmap_notify_fn(uint32_t event, char *key, void *old_value, void *value, void *user_data)
{
icmap_track_t icmap_track = (icmap_track_t)user_data;
struct icmap_item *new_item = (struct icmap_item *)value;
struct icmap_item *old_item = (struct icmap_item *)old_value;
struct icmap_notify_value new_val;
struct icmap_notify_value old_val;
if (value == NULL && old_value == NULL) {
return ;
}
if (new_item != NULL) {
new_val.type = new_item->type;
new_val.len = new_item->value_len;
new_val.data = new_item->value;
} else {
memset(&new_val, 0, sizeof(new_val));
}
/*
* old_item == new_item if fast functions are used -> don't fill old value
*/
if (old_item != NULL && old_item != new_item) {
old_val.type = old_item->type;
old_val.len = old_item->value_len;
old_val.data = old_item->value;
} else {
memset(&old_val, 0, sizeof(old_val));
}
icmap_track->notify_fn(icmap_qbtt_to_tt(event),
key,
new_val,
old_val,
icmap_track->user_data);
}
cs_error_t icmap_track_add(
const char *key_name,
int32_t track_type,
icmap_notify_fn_t notify_fn,
void *user_data,
icmap_track_t *icmap_track)
{
int32_t err;
if (notify_fn == NULL || icmap_track == NULL) {
return (CS_ERR_INVALID_PARAM);
}
if ((track_type & ~(ICMAP_TRACK_ADD | ICMAP_TRACK_DELETE | ICMAP_TRACK_MODIFY | ICMAP_TRACK_PREFIX)) != 0) {
return (CS_ERR_INVALID_PARAM);
}
*icmap_track = malloc(sizeof(**icmap_track));
if (*icmap_track == NULL) {
return (CS_ERR_NO_MEMORY);
}
memset(*icmap_track, 0, sizeof(**icmap_track));
if (key_name != NULL) {
(*icmap_track)->key_name = strdup(key_name);
};
(*icmap_track)->track_type = track_type;
(*icmap_track)->notify_fn = notify_fn;
(*icmap_track)->user_data = user_data;
if ((err = qb_map_notify_add(icmap_global_map->qb_map, (*icmap_track)->key_name, icmap_notify_fn,
icmap_tt_to_qbtt(track_type), *icmap_track)) != 0) {
free((*icmap_track)->key_name);
free(*icmap_track);
return (qb_to_cs_error(err));
}
qb_list_init(&(*icmap_track)->list);
qb_list_add (&(*icmap_track)->list, &icmap_track_list_head);
return (CS_OK);
}
cs_error_t icmap_track_delete(icmap_track_t icmap_track)
{
int32_t err;
if ((err = qb_map_notify_del_2(icmap_global_map->qb_map, icmap_track->key_name,
icmap_notify_fn, icmap_tt_to_qbtt(icmap_track->track_type), icmap_track)) != 0) {
return (qb_to_cs_error(err));
}
qb_list_del(&icmap_track->list);
free(icmap_track->key_name);
free(icmap_track);
return (CS_OK);
}
void *icmap_track_get_user_data(icmap_track_t icmap_track)
{
return (icmap_track->user_data);
}
cs_error_t icmap_set_ro_access(const char *key_name, int prefix, int ro_access)
{
struct qb_list_head *iter, *tmp_iter;
struct icmap_ro_access_item *icmap_ro_ai;
qb_list_for_each_safe(iter, tmp_iter, &icmap_ro_access_item_list_head) {
icmap_ro_ai = qb_list_entry(iter, struct icmap_ro_access_item, list);
if (icmap_ro_ai->prefix == prefix && strcmp(key_name, icmap_ro_ai->key_name) == 0) {
/*
* We found item
*/
if (ro_access) {
return (CS_ERR_EXIST);
} else {
qb_list_del(&icmap_ro_ai->list);
free(icmap_ro_ai->key_name);
free(icmap_ro_ai);
return (CS_OK);
}
}
}
if (!ro_access) {
return (CS_ERR_NOT_EXIST);
}
icmap_ro_ai = malloc(sizeof(*icmap_ro_ai));
if (icmap_ro_ai == NULL) {
return (CS_ERR_NO_MEMORY);
}
memset(icmap_ro_ai, 0, sizeof(*icmap_ro_ai));
icmap_ro_ai->key_name = strdup(key_name);
if (icmap_ro_ai->key_name == NULL) {
free(icmap_ro_ai);
return (CS_ERR_NO_MEMORY);
}
icmap_ro_ai->prefix = prefix;
qb_list_init(&icmap_ro_ai->list);
qb_list_add (&icmap_ro_ai->list, &icmap_ro_access_item_list_head);
return (CS_OK);
}
int icmap_is_key_ro(const char *key_name)
{
struct qb_list_head *iter;
struct icmap_ro_access_item *icmap_ro_ai;
qb_list_for_each(iter, &icmap_ro_access_item_list_head) {
icmap_ro_ai = qb_list_entry(iter, struct icmap_ro_access_item, list);
if (icmap_ro_ai->prefix) {
if (strlen(icmap_ro_ai->key_name) > strlen(key_name))
continue;
if (strncmp(icmap_ro_ai->key_name, key_name, strlen(icmap_ro_ai->key_name)) == 0) {
return (CS_TRUE);
}
} else {
if (strcmp(icmap_ro_ai->key_name, key_name) == 0) {
return (CS_TRUE);
}
}
}
return (CS_FALSE);
}
cs_error_t icmap_copy_map(icmap_map_t dst_map, const icmap_map_t src_map)
{
icmap_iter_t iter;
size_t value_len;
icmap_value_types_t value_type;
const char *key_name;
cs_error_t err;
void *value;
iter = icmap_iter_init_r(src_map, NULL);
if (iter == NULL) {
return (CS_ERR_NO_MEMORY);
}
err = CS_OK;
while ((key_name = icmap_iter_next(iter, &value_len, &value_type)) != NULL) {
err = icmap_get_ref_r(src_map, key_name, &value, &value_len, &value_type);
if (err != CS_OK) {
goto exit_iter_finalize;
}
err = icmap_set_r(dst_map, key_name, value, value_len, value_type);
if (err != CS_OK) {
goto exit_iter_finalize;
}
}
exit_iter_finalize:
icmap_iter_finalize(iter);
return (err);
}
diff --git a/include/corosync/icmap.h b/include/corosync/icmap.h
index b168376c..cc571fb5 100644
--- a/include/corosync/icmap.h
+++ b/include/corosync/icmap.h
@@ -1,565 +1,566 @@
/*
* Copyright (c) 2011-2017 Red Hat, Inc.
*
* Author: Jan Friesse (jfriesse@redhat.com)
*
* All rights reserved.
*
* This software licensed under BSD license, the text of which follows:
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* - Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* - Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
* - Neither the name of the Red Hat, Inc. nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
#ifndef ICMAP_H_DEFINED
#define ICMAP_H_DEFINED
#include <stdlib.h>
#include <corosync/corotypes.h>
#include <qb/qbmap.h>
#ifdef __cplusplus
extern "C" {
#endif
/**
* Maximum length of key in icmap
*/
#define ICMAP_KEYNAME_MAXLEN 255
/**
* Minimum lenght of key in icmap
*/
#define ICMAP_KEYNAME_MINLEN 3
/**
* Possible types of value. Binary is raw data without trailing zero with given length
*/
typedef enum {
ICMAP_VALUETYPE_INT8 = 1,
ICMAP_VALUETYPE_UINT8 = 2,
ICMAP_VALUETYPE_INT16 = 3,
ICMAP_VALUETYPE_UINT16 = 4,
ICMAP_VALUETYPE_INT32 = 5,
ICMAP_VALUETYPE_UINT32 = 6,
ICMAP_VALUETYPE_INT64 = 7,
ICMAP_VALUETYPE_UINT64 = 8,
ICMAP_VALUETYPE_FLOAT = 9,
ICMAP_VALUETYPE_DOUBLE = 10,
ICMAP_VALUETYPE_STRING = 11,
ICMAP_VALUETYPE_BINARY = 12,
+ ICMAP_VALUETYPE_BOOLEAN = 13,
} icmap_value_types_t;
/*
* Tracking values.
*/
#define ICMAP_TRACK_ADD 4
#define ICMAP_TRACK_DELETE 1
#define ICMAP_TRACK_MODIFY 2
/**
* Whole prefix is tracked, instead of key only (so "totem." tracking means that
* "totem.nodeid", "totem.version", ... applies). This value is also never returned
* inside of callback and is used only in adding track
*/
#define ICMAP_TRACK_PREFIX 8
/**
* Structure passed as new_value and old_value in change callback. It contains type of
* key, length of key and pointer to value of key
*/
struct icmap_notify_value {
icmap_value_types_t type;
size_t len;
const void *data;
};
/**
* Prototype for notify callback function. Even is one of ICMAP_TRACK_* event, key_name is
* changed key, new and old_value contains values or are zeroed (in other words, type is non
* existing 0 type) if there were no old (creating of key) or new (deleting of key) value.
* user_data are passed when adding tracking.
*/
typedef void (*icmap_notify_fn_t) (
int32_t event,
const char *key_name,
struct icmap_notify_value new_value,
struct icmap_notify_value old_value,
void *user_data);
/**
* @brief icmap type.
*
* icmap.c contains global variable (icmap_global_map) of this type. This
* is used in every non-reentant call. Also only in this table are implemented
* operations like set_ro and tracking of values. Other tables (created by
* icmap_init_r) are simple map tables with get/set/iter operations.
*/
typedef struct icmap_map *icmap_map_t;
/**
* @brief Itterator type
*/
typedef qb_map_iter_t *icmap_iter_t;
/**
* @brief Track type
*/
typedef struct icmap_track *icmap_track_t;
/**
* @brief Initialize global icmap
* @return
*/
extern cs_error_t icmap_init(void);
/**
* @brief Initialize additional (local, reentrant) icmap_map. Content of variable
* result is undefined if return code is not CS_OK.
* @param result
* @return
*/
extern cs_error_t icmap_init_r(icmap_map_t *result);
/**
* @brief Finalize global icmap
*/
extern void icmap_fini(void);
/**
* @brief Finalize local, reentrant icmap
* @param map
*/
extern void icmap_fini_r(const icmap_map_t map);
/**
* @brief Return global icmap
* @return
*/
extern icmap_map_t icmap_get_global_map(void);
/**
* @brief Compare value of key with name key_name1 in map1 with key with name key_name2
* in map2.
*
* Two values must have same type, length and value to be considered equal.
* Function returns 0 when any of map1, key_name1, map2, key_name2 are NULL, or
* key_name is not found in map, or keys are not equal. != 0 is returned when
* values are equal.
*
* @param map1
* @param key_name1
* @param map2
* @param key_name2
* @return
*/
extern int icmap_key_value_eq(
const icmap_map_t map1,
const char *key_name1,
const icmap_map_t map2,
const char *key_name2);
/**
* @brief Store value with value_len length and type as key_name name in global icmap.
* @param key_name
* @param value
* @param value_len
* @param type
* @return
*/
extern cs_error_t icmap_set(
const char *key_name,
const void *value,
size_t value_len,
icmap_value_types_t type);
/**
* @brief Reentrant version of icmap_set
* @param map
* @param key_name
* @param value
* @param value_len
* @param type
* @return
*/
extern cs_error_t icmap_set_r(
const icmap_map_t map,
const char *key_name,
const void *value,
size_t value_len,
icmap_value_types_t type);
/*
* Shortcuts for setting values
*/
extern cs_error_t icmap_set_int8(const char *key_name, int8_t value);
extern cs_error_t icmap_set_uint8(const char *key_name, uint8_t value);
extern cs_error_t icmap_set_int16(const char *key_name, int16_t value);
extern cs_error_t icmap_set_uint16(const char *key_name, uint16_t value);
extern cs_error_t icmap_set_int32(const char *key_name, int32_t value);
extern cs_error_t icmap_set_uint32(const char *key_name, uint32_t value);
extern cs_error_t icmap_set_int64(const char *key_name, int64_t value);
extern cs_error_t icmap_set_uint64(const char *key_name, uint64_t value);
extern cs_error_t icmap_set_float(const char *key_name, float value);
extern cs_error_t icmap_set_double(const char *key_name, double value);
extern cs_error_t icmap_set_string(const char *key_name, const char *value);
extern cs_error_t icmap_set_int8_r(const icmap_map_t map, const char *key_name, int8_t value);
extern cs_error_t icmap_set_uint8_r(const icmap_map_t map, const char *key_name, uint8_t value);
extern cs_error_t icmap_set_int16_r(const icmap_map_t map, const char *key_name, int16_t value);
extern cs_error_t icmap_set_uint16_r(const icmap_map_t map, const char *key_name, uint16_t value);
extern cs_error_t icmap_set_int32_r(const icmap_map_t map, const char *key_name, int32_t value);
extern cs_error_t icmap_set_uint32_r(const icmap_map_t map, const char *key_name, uint32_t value);
extern cs_error_t icmap_set_int64_r(const icmap_map_t map, const char *key_name, int64_t value);
extern cs_error_t icmap_set_uint64_r(const icmap_map_t map, const char *key_name, uint64_t value);
extern cs_error_t icmap_set_float_r(const icmap_map_t map, const char *key_name, float value);
extern cs_error_t icmap_set_double_r(const icmap_map_t map, const char *key_name, double value);
extern cs_error_t icmap_set_string_r(const icmap_map_t map, const char *key_name, const char *value);
/**
* @brief Delete key from map
* @param key_name
* @return
*/
extern cs_error_t icmap_delete(const char *key_name);
/**
* @brief icmap_delete_r
* @param map
* @param key_name
* @return
*/
extern cs_error_t icmap_delete_r(const icmap_map_t map, const char *key_name);
/**
* @brief Retrieve value of key key_name and store it in user preallocated value pointer.
*
* Value can be NULL, and then only value_len and/or type is returned (both of them
* can also be NULL). If value is not NULL, actual length of value in map is checked
* against value_len. If *value_len is shorter then length of value in map, error
* CS_ERR_INVALID_PARAM is returned. After successful copy of value, value_len is
* set to actual length of value in map.
*
* @param key_name
* @param value
* @param value_len
* @param type
* @return
*/
extern cs_error_t icmap_get(
const char *key_name,
void *value,
size_t *value_len,
icmap_value_types_t *type);
/**
* @brief Same as icmap_get but it's reentrant and operates on given icmap_map
* @param map
* @param key_name
* @param value
* @param value_len
* @param type
* @return
*/
extern cs_error_t icmap_get_r(
const icmap_map_t map,
const char *key_name,
void *value,
size_t *value_len,
icmap_value_types_t *type);
/*
* Shortcuts for icmap_get
*/
extern cs_error_t icmap_get_int8(const char *key_name, int8_t *i8);
extern cs_error_t icmap_get_uint8(const char *key_name, uint8_t *u8);
extern cs_error_t icmap_get_int16(const char *key_name, int16_t *i16);
extern cs_error_t icmap_get_uint16(const char *key_name, uint16_t *u16);
extern cs_error_t icmap_get_int32(const char *key_name, int32_t *i32);
extern cs_error_t icmap_get_uint32(const char *key_name, uint32_t *u32);
extern cs_error_t icmap_get_int64(const char *key_name, int64_t *i64);
extern cs_error_t icmap_get_uint64(const char *key_name, uint64_t *u64);
extern cs_error_t icmap_get_float(const char *key_name, float *flt);
extern cs_error_t icmap_get_double(const char *key_name, double *dbl);
/*
* Shortcuts for icmap_get_r
*/
extern cs_error_t icmap_get_int8_r(const icmap_map_t map, const char *key_name, int8_t *i8);
extern cs_error_t icmap_get_uint8_r(const icmap_map_t map, const char *key_name, uint8_t *u8);
extern cs_error_t icmap_get_int16_r(const icmap_map_t map, const char *key_name, int16_t *i16);
extern cs_error_t icmap_get_uint16_r(const icmap_map_t map, const char *key_name, uint16_t *u16);
extern cs_error_t icmap_get_int32_r(const icmap_map_t map, const char *key_name, int32_t *i32);
extern cs_error_t icmap_get_uint32_r(const icmap_map_t map, const char *key_name, uint32_t *u32);
extern cs_error_t icmap_get_int64_r(const icmap_map_t map, const char *key_name, int64_t *i64);
extern cs_error_t icmap_get_uint64_r(const icmap_map_t map, const char *key_name, uint64_t *u64);
extern cs_error_t icmap_get_float_r(const icmap_map_t map, const char *key_name, float *flt);
extern cs_error_t icmap_get_double_r(const icmap_map_t map, const char *key_name, double *dbl);
extern cs_error_t icmap_get_string_r(const icmap_map_t map, const char *key_name, char **str);
/**
* @brief Shortcut for icmap_get for string type.
*
* Returned string is newly allocated and
* caller is responsible for freeing memory
*
* @param key_name
* @param str
* @return
*/
extern cs_error_t icmap_get_string(const char *key_name, char **str);
/**
* @brief icmap_adjust_int
*
* Defined only for [u]int* values. It adds step to current value.
*
* @param key_name
* @param step
* @return
*/
extern cs_error_t icmap_adjust_int(const char *key_name, int32_t step);
/**
* @brief icmap_adjust_int_r
* @param map
* @param key_name
* @param step
* @return
*/
extern cs_error_t icmap_adjust_int_r(const icmap_map_t map, const char *key_name, int32_t step);
/**
* @brief icmap_fast_adjust_int
*
* Defined only for [u]int* values. It adds step to current value. Difference
* between this function and icmap_adjust_int is given in fact, that in
* tracking callback, old value is undefined, but whole process is done
* without malloc/memcpy.
*
* @param key_name
* @param step
* @return
*/
extern cs_error_t icmap_fast_adjust_int(const char *key_name, int32_t step);
/**
* @brief icmap_fast_adjust_int_r
* @param map
* @param key_name
* @param step
* @return
*/
extern cs_error_t icmap_fast_adjust_int_r(const icmap_map_t map, const char *key_name, int32_t step);
/**
* @brief Increase stored value by one
* @param key_name
* @return
*/
extern cs_error_t icmap_inc(const char *key_name);
/**
* @brief icmap_inc_r
* @param map
* @param key_name
* @return
*/
extern cs_error_t icmap_inc_r(const icmap_map_t map, const char *key_name);
/**
* @brief Decrease stored value by one
* @param key_name
* @return
*/
extern cs_error_t icmap_dec(const char *key_name);
/**
* @brief icmap_dec_r
* @param map
* @param key_name
* @return
*/
extern cs_error_t icmap_dec_r(const icmap_map_t map, const char *key_name);
/**
* @brief Increase stored value by one.
*
* Difference between this function and icmap_inc
* is same as between icmap_adjust_int and icmap_fast_adjust_int.
*
* @param key_name
* @return
*/
extern cs_error_t icmap_fast_inc(const char *key_name);
/**
* @brief icmap_fast_inc_r
* @param map
* @param key_name
* @return
*/
extern cs_error_t icmap_fast_inc_r(const icmap_map_t map, const char *key_name);
/**
* @brief Decrease stored value by one.
*
* Difference between this function and icmap_dec
* is same as between icmap_adjust_int and icmap_fast_adjust_int.
*
* @param key_name
* @return
*/
extern cs_error_t icmap_fast_dec(const char *key_name);
/**
* @brief icmap_fast_dec_r
* @param map
* @param key_name
* @return
*/
extern cs_error_t icmap_fast_dec_r(const icmap_map_t map, const char *key_name);
/**
* @brief Initialize iterator with given prefix
* @param prefix
* @return
*/
extern icmap_iter_t icmap_iter_init(const char *prefix);
/**
* @brief icmap_iter_init_r
* @param map
* @param prefix
* @return
*/
extern icmap_iter_t icmap_iter_init_r(const icmap_map_t map, const char *prefix);
/**
* @brief Return next item in iterator iter.
*
* value_len and type are optional (= can be NULL), but if set, length of returned value
* and/or type is returned. Function returns following key_name or NULL if iteration is over.
*
* @param iter
* @param value_len
* @param type
* @return
*/
extern const char *icmap_iter_next(icmap_iter_t iter, size_t *value_len, icmap_value_types_t *type);
/**
* @brief Finalize iterator
* @param iter
*/
extern void icmap_iter_finalize(icmap_iter_t iter);
/**
* @brief Add tracking function for given key_name.
*
* Tracked changes (add|modify|delete) depend on track_type, which is bitwise or of ICMAP_TRACK_* values.
* notify_fn is called on change, where user_data pointer is passed (unchanged).
* Value which can be used to delete tracking is passed as icmap_track.
*
* @param key_name
* @param track_type
* @param notify_fn
* @param user_data
* @param icmap_track
* @return
*/
extern cs_error_t icmap_track_add(
const char *key_name,
int32_t track_type,
icmap_notify_fn_t notify_fn,
void *user_data,
icmap_track_t *icmap_track);
/**
* @brief Return user data associated with given track
* @param icmap_track
* @return
*/
extern void *icmap_track_get_user_data(icmap_track_t icmap_track);
/**
* @brief Remove previously added track
* @param icmap_track
* @return
*/
extern cs_error_t icmap_track_delete(icmap_track_t icmap_track);
/**
* @brief Set read-only access for given key (key_name) or prefix,
* If prefix is set. ro_access can be !0, which means, that old information
* about ro of this key is deleted. Read-only access is used only in CMAP service!
* (in other word it prevents users from deleting/changing key, but doesn't
* guarantee anything for internal icmap users.)
* @param key_name
* @param prefix
* @param ro_access
* @return
*/
extern cs_error_t icmap_set_ro_access(const char *key_name, int prefix, int ro_access);
/**
* @brief Check in given key is read only. Returns !0 if so, otherwise (key is rw) 0.
* @param key_name
* @return
*/
extern int icmap_is_key_ro(const char *key_name);
/**
* @brief Converts given key_name to valid key name (replacing all prohibited characters by _)
* @param key_name
*/
extern void icmap_convert_name_to_valid_name(char *key_name);
/**
* @brief Copy content of src_map icmap to dst_map icmap.
* @param dst_map
* @param src_map
* @return
*/
extern cs_error_t icmap_copy_map(icmap_map_t dst_map, const icmap_map_t src_map);
/*
* Returns length of value of given type, or 0 for string and binary data type
*/
size_t icmap_get_valuetype_len(icmap_value_types_t type);
/*
* Converts track type of icmap to qb
*/
int32_t icmap_tt_to_qbtt(int32_t track_type);
/*
* Convert track type of qb to icmap
*/
int32_t icmap_qbtt_to_tt(int32_t track_type);
#ifdef __cplusplus
}
#endif
#endif /* ICMAP_H_DEFINED */
File Metadata
Details
Attached
Mime Type
text/x-diff
Expires
Sat, Jan 25, 7:09 AM (1 d, 19 h)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
1321617
Default Alt Text
(95 KB)
Attached To
Mode
rC Corosync
Attached
Detach File
Event Timeline
Log In to Comment