data_provider_opts.c revision ddd21d5dc3c89712d9286d1f66f4b2af73651cf2
/*
SSSD
Data Provider Helpers
Copyright (C) Simo Sorce <ssorce@redhat.com> 2009
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "data_provider.h"
/* =Retrieve-Options====================================================== */
int dp_get_options(TALLOC_CTX *memctx,
struct confdb_ctx *cdb,
const char *conf_path,
struct dp_option *def_opts,
int num_opts,
struct dp_option **_opts)
{
struct dp_option *opts;
int i, ret;
opts = talloc_zero_array(memctx, struct dp_option, num_opts);
if (!opts) return ENOMEM;
for (i = 0; i < num_opts; i++) {
char *tmp;
opts[i].opt_name = def_opts[i].opt_name;
opts[i].type = def_opts[i].type;
opts[i].def_val = def_opts[i].def_val;
switch (def_opts[i].type) {
case DP_OPT_STRING:
ret = confdb_get_string(cdb, opts, conf_path,
opts[i].opt_name,
opts[i].def_val.cstring,
&opts[i].val.string);
if (ret != EOK ||
((opts[i].def_val.string != NULL) &&
(opts[i].val.string == NULL))) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Failed to retrieve value for option (%s)\n",
opts[i].opt_name);
if (ret == EOK) ret = EINVAL;
goto done;
}
DEBUG(SSSDBG_TRACE_FUNC, "Option %s has%s value %s\n",
opts[i].opt_name,
opts[i].val.cstring ? "" : " no",
opts[i].val.cstring ? opts[i].val.cstring : "");
break;
case DP_OPT_BLOB:
ret = confdb_get_string(cdb, opts, conf_path,
opts[i].opt_name,
NULL, &tmp);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Failed to retrieve value for option (%s)\n",
opts[i].opt_name);
goto done;
}
if (tmp) {
opts[i].val.blob.data = (uint8_t *)tmp;
opts[i].val.blob.length = strlen(tmp);
} else if (opts[i].def_val.blob.data != NULL) {
opts[i].val.blob.data = opts[i].def_val.blob.data;
opts[i].val.blob.length = opts[i].def_val.blob.length;
} else {
opts[i].val.blob.data = NULL;
opts[i].val.blob.length = 0;
}
DEBUG(SSSDBG_TRACE_FUNC, "Option %s has %s binary value.\n",
opts[i].opt_name, opts[i].val.blob.length?"a":"no");
break;
case DP_OPT_NUMBER:
ret = confdb_get_int(cdb, conf_path,
opts[i].opt_name,
opts[i].def_val.number,
&opts[i].val.number);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Failed to retrieve value for option (%s)\n",
opts[i].opt_name);
goto done;
}
DEBUG(SSSDBG_TRACE_FUNC, "Option %s has value %d\n",
opts[i].opt_name, opts[i].val.number);
break;
case DP_OPT_BOOL:
ret = confdb_get_bool(cdb, conf_path,
opts[i].opt_name,
opts[i].def_val.boolean,
&opts[i].val.boolean);
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Failed to retrieve value for option (%s)\n",
opts[i].opt_name);
goto done;
}
DEBUG(SSSDBG_TRACE_FUNC, "Option %s is %s\n",
opts[i].opt_name, opts[i].val.boolean?"TRUE":"FALSE");
break;
}
}
ret = EOK;
*_opts = opts;
done:
if (ret != EOK) talloc_zfree(opts);
return ret;
}
/* =Basic-Option-Helpers================================================== */
int dp_copy_options(TALLOC_CTX *memctx,
struct dp_option *src_opts,
int num_opts,
struct dp_option **_opts)
{
struct dp_option *opts;
int i, ret = EOK;
opts = talloc_zero_array(memctx, struct dp_option, num_opts);
if (!opts) return ENOMEM;
for (i = 0; i < num_opts; i++) {
opts[i].opt_name = src_opts[i].opt_name;
opts[i].type = src_opts[i].type;
opts[i].def_val = src_opts[i].def_val;
ret = EOK;
switch (src_opts[i].type) {
case DP_OPT_STRING:
if (src_opts[i].val.string) {
ret = dp_opt_set_string(opts, i, src_opts[i].val.string);
} else if (src_opts[i].def_val.string) {
ret = dp_opt_set_string(opts, i, src_opts[i].def_val.string);
}
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Failed to copy value for option (%s)\n",
opts[i].opt_name);
goto done;
}
DEBUG(SSSDBG_TRACE_FUNC, "Option %s has%s value %s\n",
opts[i].opt_name,
opts[i].val.cstring ? "" : " no",
opts[i].val.cstring ? opts[i].val.cstring : "");
break;
case DP_OPT_BLOB:
if (src_opts[i].val.blob.data) {
ret = dp_opt_set_blob(opts, i, src_opts[i].val.blob);
} else if (src_opts[i].def_val.blob.data) {
ret = dp_opt_set_blob(opts, i, src_opts[i].def_val.blob);
}
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Failed to retrieve value for option (%s)\n",
opts[i].opt_name);
goto done;
}
DEBUG(SSSDBG_TRACE_FUNC, "Option %s has %s binary value.\n",
opts[i].opt_name, opts[i].val.blob.length?"a":"no");
break;
case DP_OPT_NUMBER:
if (src_opts[i].val.number) {
ret = dp_opt_set_int(opts, i, src_opts[i].val.number);
} else if (src_opts[i].def_val.number) {
ret = dp_opt_set_int(opts, i, src_opts[i].def_val.number);
}
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Failed to retrieve value for option (%s)\n",
opts[i].opt_name);
goto done;
}
DEBUG(SSSDBG_TRACE_FUNC, "Option %s has value %d\n",
opts[i].opt_name, opts[i].val.number);
break;
case DP_OPT_BOOL:
if (src_opts[i].val.boolean) {
ret = dp_opt_set_bool(opts, i, src_opts[i].val.boolean);
} else if (src_opts[i].def_val.boolean) {
ret = dp_opt_set_bool(opts, i, src_opts[i].def_val.boolean);
}
if (ret != EOK) {
DEBUG(SSSDBG_CRIT_FAILURE,
"Failed to retrieve value for option (%s)\n",
opts[i].opt_name);
goto done;
}
DEBUG(SSSDBG_TRACE_FUNC, "Option %s is %s\n",
opts[i].opt_name, opts[i].val.boolean?"TRUE":"FALSE");
break;
}
}
*_opts = opts;
done:
if (ret != EOK) talloc_zfree(opts);
return ret;
}
static const char *dp_opt_type_to_string(enum dp_opt_type type)
{
switch (type) {
case DP_OPT_STRING:
return "String";
case DP_OPT_BLOB:
return "Blob";
case DP_OPT_NUMBER:
return "Number";
case DP_OPT_BOOL:
return "Boolean";
}
return NULL;
}
/* Getters */
const char *_dp_opt_get_cstring(struct dp_option *opts,
int id, const char *location)
{
if (opts[id].type != DP_OPT_STRING) {
DEBUG(SSSDBG_FATAL_FAILURE,
"[%s] Requested type 'String' for option '%s'"
" but value is of type '%s'!\n",
location, opts[id].opt_name,
dp_opt_type_to_string(opts[id].type));
return NULL;
}
return opts[id].val.cstring;
}
char *_dp_opt_get_string(struct dp_option *opts,
int id, const char *location)
{
if (opts[id].type != DP_OPT_STRING) {
DEBUG(SSSDBG_FATAL_FAILURE,
"[%s] Requested type 'String' for option '%s'"
" but value is of type '%s'!\n",
location, opts[id].opt_name,
dp_opt_type_to_string(opts[id].type));
return NULL;
}
return opts[id].val.string;
}
struct dp_opt_blob _dp_opt_get_blob(struct dp_option *opts,
int id, const char *location)
{
struct dp_opt_blob null_blob = { NULL, 0 };
if (opts[id].type != DP_OPT_BLOB) {
DEBUG(SSSDBG_FATAL_FAILURE, "[%s] Requested type 'Blob' for option '%s'"
" but value is of type '%s'!\n",
location, opts[id].opt_name,
dp_opt_type_to_string(opts[id].type));
return null_blob;
}
return opts[id].val.blob;
}
int _dp_opt_get_int(struct dp_option *opts,
int id, const char *location)
{
if (opts[id].type != DP_OPT_NUMBER) {
DEBUG(SSSDBG_FATAL_FAILURE,
"[%s] Requested type 'Number' for option '%s'"
" but value is of type '%s'!\n",
location, opts[id].opt_name,
dp_opt_type_to_string(opts[id].type));
return 0;
}
return opts[id].val.number;
}
bool _dp_opt_get_bool(struct dp_option *opts,
int id, const char *location)
{
if (opts[id].type != DP_OPT_BOOL) {
DEBUG(SSSDBG_FATAL_FAILURE,
"[%s] Requested type 'Boolean' for option '%s'"
" but value is of type '%s'!\n",
location, opts[id].opt_name,
dp_opt_type_to_string(opts[id].type));
return false;
}
return opts[id].val.boolean;
}
/* Setters */
int _dp_opt_set_string(struct dp_option *opts, int id,
const char *s, const char *location)
{
if (opts[id].type != DP_OPT_STRING) {
DEBUG(SSSDBG_FATAL_FAILURE,
"[%s] Requested type 'String' for option '%s'"
" but type is '%s'!\n",
location, opts[id].opt_name,
dp_opt_type_to_string(opts[id].type));
return EINVAL;
}
if (opts[id].val.string) {
talloc_zfree(opts[id].val.string);
}
if (s) {
opts[id].val.string = talloc_strdup(opts, s);
if (!opts[id].val.string) {
DEBUG(SSSDBG_FATAL_FAILURE, "talloc_strdup() failed!\n");
return ENOMEM;
}
}
return EOK;
}
int _dp_opt_set_blob(struct dp_option *opts, int id,
struct dp_opt_blob b, const char *location)
{
if (opts[id].type != DP_OPT_BLOB) {
DEBUG(SSSDBG_FATAL_FAILURE, "[%s] Requested type 'Blob' for option '%s'"
" but type is '%s'!\n",
location, opts[id].opt_name,
dp_opt_type_to_string(opts[id].type));
return EINVAL;
}
if (opts[id].val.blob.data) {
talloc_zfree(opts[id].val.blob.data);
opts[id].val.blob.length = 0;
}
if (b.data) {
opts[id].val.blob.data = talloc_memdup(opts, b.data, b.length);
if (!opts[id].val.blob.data) {
DEBUG(SSSDBG_FATAL_FAILURE, "talloc_memdup() failed!\n");
return ENOMEM;
}
}
opts[id].val.blob.length = b.length;
return EOK;
}
int _dp_opt_set_int(struct dp_option *opts, int id,
int i, const char *location)
{
if (opts[id].type != DP_OPT_NUMBER) {
DEBUG(SSSDBG_FATAL_FAILURE,
"[%s] Requested type 'Number' for option '%s'"
" but type is '%s'!\n",
location, opts[id].opt_name,
dp_opt_type_to_string(opts[id].type));
return EINVAL;
}
opts[id].val.number = i;
return EOK;
}
int _dp_opt_set_bool(struct dp_option *opts, int id,
bool b, const char *location)
{
if (opts[id].type != DP_OPT_BOOL) {
DEBUG(SSSDBG_FATAL_FAILURE,
"[%s] Requested type 'Boolean' for option '%s'"
" but type is '%s'!\n",
location, opts[id].opt_name,
dp_opt_type_to_string(opts[id].type));
return EINVAL;
}
opts[id].val.boolean = b;
return EOK;
}