summaryrefslogtreecommitdiff
path: root/common
diff options
context:
space:
mode:
authorStephen Gallagher <sgallagh@redhat.com>2009-09-28 09:36:00 -0400
committerStephen Gallagher <sgallagh@redhat.com>2009-10-05 10:32:09 -0400
commite3a794633b02411c3d3adc4443e98541f045f41a (patch)
tree258c48cff793720fd22be1246c97ed0eafbce69d /common
parent70b0f90d49bc5b89d700c4275641d5133b8a2ee0 (diff)
downloadsssd-e3a794633b02411c3d3adc4443e98541f045f41a.tar.gz
sssd-e3a794633b02411c3d3adc4443e98541f045f41a.tar.bz2
sssd-e3a794633b02411c3d3adc4443e98541f045f41a.zip
INI Add config_from_fd() to ini_config
Patch adds ability to read configuration using already open file descriptor. Started by Steve G and refined a bit by me.
Diffstat (limited to 'common')
-rw-r--r--common/ini/ini_config.c164
-rw-r--r--common/ini/ini_config.h23
-rw-r--r--common/ini/ini_config_ut.c74
3 files changed, 239 insertions, 22 deletions
diff --git a/common/ini/ini_config.c b/common/ini/ini_config.c
index ffc59603..bd4fa79c 100644
--- a/common/ini/ini_config.c
+++ b/common/ini/ini_config.c
@@ -27,6 +27,7 @@
#include <ctype.h>
#include <stdlib.h>
#include <locale.h>
+#include <fcntl.h>
#include "config.h"
/* For error text */
#include <libintl.h>
@@ -75,6 +76,17 @@
#define INI_ERROR "errors"
#define INI_ERROR_NAME "errname"
+/* Internally used functions */
+static int config_with_lines(const char *application,
+ FILE *config_file,
+ const char *config_source,
+ struct collection_item **ini_config,
+ int error_level,
+ struct collection_item **error_list,
+ struct collection_item **lines);
+
+
+
/* Different error string functions can be passed as callbacks */
typedef const char * (*error_fn)(int error);
@@ -153,13 +165,13 @@ int read_line(FILE *file,
/***************************************************************************/
/* Function to read single ini file and pupulate
* the provided collection with subcollcetions from the file */
-static int ini_to_collection(const char *filename,
+static int ini_to_collection(FILE *file,
+ const char *config_filename,
struct collection_item *ini_config,
int error_level,
struct collection_item **error_list,
struct collection_item **lines)
{
- FILE *file;
int error;
int status;
int section_count = 0;
@@ -176,12 +188,9 @@ static int ini_to_collection(const char *filename,
TRACE_FLOW_STRING("ini_to_collection", "Entry");
- /* Open file for reading */
- file = fopen(filename, "r");
if (file == NULL) {
- error = errno;
- TRACE_ERROR_NUMBER("Failed to open file - but this is OK", error);
- return ENOENT;
+ TRACE_ERROR_NUMBER("No file handle", EINVAL);
+ return EINVAL;
}
/* Open the collection of errors */
@@ -194,7 +203,7 @@ static int ini_to_collection(const char *filename,
return error;
}
/* Add file name as the first item */
- error = col_add_str_property(*error_list, NULL, INI_ERROR_NAME, filename, 0);
+ error = col_add_str_property(*error_list, NULL, INI_ERROR_NAME, config_filename, 0);
if (error) {
TRACE_ERROR_NUMBER("Failed to and name to collection", error);
fclose(file);
@@ -423,9 +432,10 @@ void free_ini_config_lines(struct collection_item *lines)
TRACE_FLOW_STRING("free_ini_config_lines", "Exit");
}
+
/* Read configuration information from a file */
int config_from_file(const char *application,
- const char *config_file,
+ const char *config_filename,
struct collection_item **ini_config,
int error_level,
struct collection_item **error_list)
@@ -434,7 +444,7 @@ int config_from_file(const char *application,
TRACE_FLOW_STRING("config_from_file", "Entry");
error = config_from_file_with_lines(application,
- config_file,
+ config_filename,
ini_config,
error_level,
error_list,
@@ -443,16 +453,97 @@ int config_from_file(const char *application,
return error;
}
+/* Read configuration information from a file descriptor */
+int config_from_fd(const char *application,
+ int fd,
+ const char *config_source,
+ struct collection_item **ini_config,
+ int error_level,
+ struct collection_item **error_list)
+{
+ int error;
+
+ TRACE_FLOW_STRING("config_from_fd", "Entry");
+ error = config_from_fd_with_lines(application, fd, config_source,
+ ini_config, error_level,
+ error_list, NULL);
+ TRACE_FLOW_NUMBER("config_from_fd. Returns", error);
+ return error;
+}
+
/* Function to read the ini file and have a collection
* of which item appers on which line
*/
int config_from_file_with_lines(const char *application,
- const char *config_file,
+ const char *config_filename,
struct collection_item **ini_config,
int error_level,
struct collection_item **error_list,
struct collection_item **lines)
{
+ int error = EOK;
+ FILE *config_file = NULL;
+
+ TRACE_FLOW_STRING("config_from_file_with_lines", "Entry");
+
+ config_file = fopen(config_filename, "r");
+ if(!config_file) {
+ error = errno;
+ TRACE_ERROR_NUMBER("Failed to open file", error);
+ return error;
+ }
+
+ error = config_with_lines(application, config_file,
+ config_filename, ini_config,
+ error_level, error_list,
+ lines);
+ TRACE_FLOW_NUMBER("config_from_file_with_lines. Returns", error);
+ return error;
+}
+
+/* Function to read the ini file and have a collection
+ * of which item appers on which line
+ */
+int config_from_fd_with_lines(const char *application,
+ int fd,
+ const char *config_source,
+ struct collection_item **ini_config,
+ int error_level,
+ struct collection_item **error_list,
+ struct collection_item **lines)
+{
+ int error = EOK;
+ FILE *config_file;
+
+ TRACE_FLOW_STRING("config_from_fd_with_lines", "Entry");
+
+ config_file = fdopen(fd, "r");
+ if (!config_file) {
+ error = errno;
+ TRACE_ERROR_NUMBER("Failed to dup file", error);
+ return error;
+ }
+
+ error = config_with_lines(application, config_file,
+ config_source, ini_config,
+ error_level, error_list,
+ lines);
+ TRACE_FLOW_NUMBER("config_from_fd_with_lines. Returns", error);
+
+ return error;
+}
+
+/* Low level function that prepares the collection
+ * and calls parser.
+ */
+static int config_with_lines(const char *application,
+ FILE *config_file,
+ const char *config_source,
+ struct collection_item **ini_config,
+ int error_level,
+ struct collection_item **error_list,
+ struct collection_item **lines)
+{
int error;
int created = 0;
int created_lines = 0;
@@ -511,8 +602,9 @@ int config_from_file_with_lines(const char *application,
}
/* Do the actual work */
- error = ini_to_collection(config_file, *ini_config,
- error_level, error_list, lines);
+ error = ini_to_collection(config_file, config_source,
+ *ini_config, error_level,
+ error_list, lines);
/* In case of error when we created collection - delete it */
if (error && created) {
col_destroy_collection(*ini_config);
@@ -528,6 +620,39 @@ int config_from_file_with_lines(const char *application,
return error;
}
+/* Special wrapper around the inernal parser
+ * to open the file first.
+ * Used in conf_for_app function.
+ */
+static int ini_to_col_from_file(const char *config_filename,
+ struct collection_item *ini_config,
+ int error_level,
+ struct collection_item **error_list,
+ struct collection_item **lines)
+{
+ int error = EOK;
+ FILE *config_file = NULL;
+
+ TRACE_FLOW_STRING("ini_to_col_from_file", "Entry");
+
+ config_file = fopen(config_filename, "r");
+ if(!config_file) {
+ error = errno;
+ TRACE_ERROR_NUMBER("ini_to_col_from_file. Returns", error);
+ return ENOENT;
+ }
+
+ error = ini_to_collection(config_file,
+ config_filename,
+ ini_config,
+ error_level,
+ error_list,
+ lines);
+ TRACE_FLOW_NUMBER("ini_to_col_from_file. Returns", error);
+ return error;
+}
+
+
/* Read default config file and then overwrite it with a specific one
* from the directory */
int config_for_app(const char *application,
@@ -605,8 +730,8 @@ int config_for_app(const char *application,
/* Read master file */
if (config_file != NULL) {
TRACE_INFO_STRING("Reading master file:", config_file);
- error = ini_to_collection(config_file, *ini_config,
- error_level, pass_common, NULL);
+ error = ini_to_col_from_file(config_file, *ini_config,
+ error_level, pass_common, NULL);
tried++;
/* ENOENT and EOK are Ok */
if (error) {
@@ -624,7 +749,7 @@ int config_for_app(const char *application,
}
/* Add error results if any to the overarching error collection */
if ((pass_common != NULL) && (*pass_common != NULL)) {
- TRACE_INFO_STRING("Process erros resulting from file:", config_file);
+ TRACE_INFO_STRING("Process errors resulting from file:", config_file);
error = col_add_collection_to_collection(*error_set, NULL, NULL,
*pass_common,
COL_ADD_MODE_EMBED);
@@ -663,10 +788,9 @@ int config_for_app(const char *application,
sprintf(file_name, "%s%s%s.conf", config_dir, SLASH, application);
TRACE_INFO_STRING("Opening file:", file_name);
-
- /* Read master file */
- error = ini_to_collection(file_name, *ini_config,
- error_level, pass_specific, NULL);
+ /* Read specific file */
+ error = ini_to_col_from_file(file_name, *ini_config,
+ error_level, pass_specific, NULL);
tried++;
free(file_name);
/* ENOENT and EOK are Ok */
diff --git a/common/ini/ini_config.h b/common/ini/ini_config.h
index 1fee48ac..5ae49814 100644
--- a/common/ini/ini_config.h
+++ b/common/ini/ini_config.h
@@ -97,23 +97,42 @@ const char *validation_error_str(int parsing_error);
/* Read configuration information from a file */
int config_from_file(const char *application, /* Name of the application - will be used as name of the collection */
- const char *config_file, /* Name of the config file - if NULL the collection will be empty */
+ const char *config_filename, /* Name of the config file - if NULL the collection will be empty */
struct collection_item **ini_config, /* If *ini_config is NULL a new ini object will be allocated, */
/* otherwise the one that is pointed to will be updated. */
int error_level, /* Error level - break for errors, warnings or best effort (don't break) */
struct collection_item **error_list); /* List of errors for a file */
+/* Read configuration information from a file descriptor */
+int config_from_fd(const char *application, /* Name of the application - will be used as name of the collection */
+ int fd, /* Previously opened file descriptor for the config file */
+ const char *config_source, /* Name of the file being parsed, for use when printing the error list */
+ struct collection_item **ini_config, /* If *ini_config is NULL a new ini object will be allocated*/
+ int error_level, /* Error level - break for errors, warnings or best effort (don't break) */
+ struct collection_item **error_list); /* List of errors for a file */
+
/* Read configuration information from a file with extra collection of line numbers */
int config_from_file_with_lines(
const char *application, /* Name of the application - will be used as name of the collection */
- const char *config_file, /* Name of the config file - if NULL the collection will be empty */
+ const char *config_filename, /* Name of the config file - if NULL the collection will be empty */
struct collection_item **ini_config, /* If *ini_config is NULL a new ini object will be allocated, */
/* otherwise the one that is pointed to will be updated. */
int error_level, /* Error level - break for errors, warnings or best effort (don't break) */
struct collection_item **error_list, /* List of errors for a file */
struct collection_item **lines); /* Collection of pairs where key is the key and value is line number */
+/* Read configuration information from a file descriptor with extra collection of line numbers */
+int config_from_fd_with_lines(
+ const char *application, /* Name of the application - will be used as name of the collection */
+ int fd, /* Previously opened file descriptor for the config file */
+ const char *config_source, /* Name of the file being parsed, for use when printing the error list */
+ struct collection_item **ini_config, /* If *ini_config is NULL a new ini object will be allocated, */
+ /* otherwise the one that is pointed to will be updated. */
+ int error_level, /* Error level - break for errors, warnings or best effort (don't break) */
+ struct collection_item **error_list, /* List of errors for a file */
+ struct collection_item **lines); /* Collection of pairs where key is the key and value is line number */
+
/* Read default config file and then overwrite it with a specific one from the directory */
int config_for_app(const char *application, /* Name of the application that will be used to get config for */
diff --git a/common/ini/ini_config_ut.c b/common/ini/ini_config_ut.c
index 6fbade6e..52e89cb1 100644
--- a/common/ini/ini_config_ut.c
+++ b/common/ini/ini_config_ut.c
@@ -23,6 +23,7 @@
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
+#include <fcntl.h>
#define TRACE_HOME
#include "ini_config.h"
#include "collection.h"
@@ -133,6 +134,78 @@ int single_file(void)
return 0;
}
+int single_fd(void)
+{
+ int error;
+ struct collection_item *ini_config = NULL;
+ struct collection_item *error_set = NULL;
+ struct collection_item *lines = NULL;
+
+ int fd = open("./ini.conf", O_RDONLY);
+ if (fd < 0) {
+ error = errno;
+ printf("Attempt to read configuration returned error: %d\n", error);
+ return error;
+ }
+
+ error = config_from_fd("test", fd, "./ini.conf", &ini_config,
+ INI_STOP_ON_NONE, &error_set);
+ if (error) {
+ printf("Attempt to read configuration returned error: %d\n",error);
+ return error;
+ }
+
+ col_debug_collection(ini_config, COL_TRAVERSE_DEFAULT);
+ col_print_collection(ini_config);
+ col_print_collection(error_set);
+
+ printf("\n\n----------------------\n");
+ /* Output parsing errors (if any) */
+ print_file_parsing_errors(stdout, error_set);
+ printf("----------------------\n\n\n");
+
+
+ free_ini_config(ini_config);
+ free_ini_config_errors(error_set);
+ close(fd);
+
+ ini_config = NULL;
+ error_set = NULL;
+
+ printf("TEST WITH LINES\n");
+
+ fd = open("./ini.conf", O_RDONLY);
+ if (fd < 0) {
+ error = errno;
+ printf("Attempt to read configuration returned error: %d\n", error);
+ return error;
+ }
+ error = config_from_fd_with_lines("test", fd,
+ "./ini.conf",
+ &ini_config,
+ INI_STOP_ON_NONE,
+ &error_set, &lines);
+ if (error) {
+ printf("Attempt to read configuration returned error: %d\n",error);
+ return error;
+ }
+
+ col_debug_collection(ini_config, COL_TRAVERSE_DEFAULT);
+ col_debug_collection(lines, COL_TRAVERSE_DEFAULT);
+
+ printf("\n\n----------------------\n");
+ /* Output parsing errors (if any) */
+ print_file_parsing_errors(stdout, error_set);
+ printf("----------------------\n\n\n");
+
+
+ free_ini_config(ini_config);
+ free_ini_config_errors(error_set);
+ free_ini_config_lines(lines);
+
+ return 0;
+}
+
int negative_test(void)
{
int error;
@@ -828,6 +901,7 @@ int main(int argc, char *argv[])
if ((error = basic_test()) ||
(error = single_file()) ||
+ (error = single_fd()) ||
(error = real_test(NULL)) ||
/* This should result in merged configuration */
(error = real_test("./ini.conf")) ||