[Ocfs2-tools-commits] jlbec commits r490 - in trunk: . clusterbo
libo2cb libo2cb/include mount.ocfs2
svn-commits at oss.oracle.com
svn-commits at oss.oracle.com
Tue Dec 14 17:59:16 CST 2004
Author: jlbec
Date: 2004-12-14 17:59:14 -0600 (Tue, 14 Dec 2004)
New Revision: 490
Added:
trunk/clusterbo/jconfig.c
trunk/clusterbo/jconfig.h
trunk/clusterbo/jiterator.c
trunk/clusterbo/jiterator.h
trunk/libo2cb/Makefile
trunk/libo2cb/include/o2cb.h
trunk/libo2cb/include/o2cb_abi.h
trunk/libo2cb/o2cb_abi.c
trunk/libo2cb/o2cb_err.et.in
Modified:
trunk/Makefile
trunk/clusterbo/Makefile
trunk/configure.in
trunk/libo2cb/
trunk/libo2cb/include/
trunk/libo2cb/include/ocfs2_heartbeat.h
trunk/libo2cb/include/ocfs2_nodemanager.h
trunk/libo2cb/include/ocfs2_tcp.h
trunk/mount.ocfs2/Makefile
Log:
o Land the libo2cb organizational changes
Modified: trunk/Makefile
===================================================================
--- trunk/Makefile 2004-12-14 23:50:34 UTC (rev 489)
+++ trunk/Makefile 2004-12-14 23:59:14 UTC (rev 490)
@@ -22,7 +22,7 @@
$(error could not detect architecture for tools)
endif
-SUBDIRS = libocfs2 fsck.ocfs2 mkfs.ocfs2 mounted.ocfs2 tunefs.ocfs2 debugfs.ocfs2 clusterbo mount.ocfs2 listuuid extras patches
+SUBDIRS = libocfs2 libo2cb fsck.ocfs2 mkfs.ocfs2 mounted.ocfs2 tunefs.ocfs2 debugfs.ocfs2 clusterbo mount.ocfs2 listuuid extras patches
ifdef BUILD_OCFS2CDSL
SUBDIRS += ocfs2cdsl
Modified: trunk/clusterbo/Makefile
===================================================================
--- trunk/clusterbo/Makefile 2004-12-14 23:50:34 UTC (rev 489)
+++ trunk/clusterbo/Makefile 2004-12-14 23:59:14 UTC (rev 490)
@@ -2,16 +2,15 @@
include $(TOPDIR)/Preamble.make
-SBIN_PROGRAMS = clusterbo o2cb_ctl
-LIBRARIES = libo2cb.a
+SBIN_PROGRAMS = clusterbo # o2cb_ctl
INCLUDES = -Iinclude -I$(TOPDIR)/libocfs2/include \
- -I$(TOPDIR)/libocfs2cluster/include
+ -I$(TOPDIR)/libo2cb/include
LIBOCFS2_LIBS = -L$(TOPDIR)/libocfs2 -locfs2
LIBOCFS2_DEPS = $(TOPDIR)/libocfs2/libocfs2.a
-LIBO2CB_LIBS = -L. -lo2cb
-LIBO2CB_DEPS = libo2cb.a
+LIBO2CB_LIBS = -L$(TOPDIR)/libo2cb -lo2cb
+LIBO2CB_DEPS = $(TOPDIR)/libo2cb/libo2cb.a
ifdef OCFS_DEBUG
OPTS += -ggdb
@@ -24,9 +23,6 @@
DEFINES = -DOCFS2_FLAT_INCLUDES -DVERSION=\"$(VERSION)\"
-LIBO2CB_CFILES = o2cb_abi.c
-LIBO2CB_OBJS = $(subst .c,.o,$(LIBO2CB_CFILES))
-
CLUSTERBO_CFILES = clusterbo.c
CLUSTERBO_OBJS = $(subst .c,.o,$(CLUSTERBO_CFILES))
@@ -37,17 +33,11 @@
HEADERS = jconfig.h jiterator.h
-CFILES = $(LIBO2CB_CFILES) $(CLUSTERBO_CFILES) $(O2CB_CTL_CFILES)
+CFILES = $(CLUSTERBO_CFILES) $(O2CB_CTL_CFILES)
DIST_FILES = $(CFILES) $(HEADERS)
DIST_RULES = dist-subdircreate
-o2cb_abi_CFLAGS = -fPIC
-libo2cb.a: $(LIBO2CB_OBJS)
- rm -f $@
- $(AR) r $@ $^
- $(RANLIB) $@
-
clusterbo: $(CLUSTERBO_OBJS) $(LIBOCFS2_DEPS)
$(LINK) $(LIBOCFS2_LIBS) $(COM_ERR_LIBS)
Added: trunk/clusterbo/jconfig.c
===================================================================
--- trunk/clusterbo/jconfig.c 2004-12-14 23:50:34 UTC (rev 489)
+++ trunk/clusterbo/jconfig.c 2004-12-14 23:59:14 UTC (rev 490)
@@ -0,0 +1,1727 @@
+/*
+ * jconfig.c
+ *
+ * Routines for handling the config file format of
+ * Helpers::JConfig.
+ *
+ * Copyright (C) 2002 Joel Becker <jlbec at evilplan.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+/* Check G_LOG_DOMAIN before including glib.h */
+#ifndef G_LOG_DOMAIN
+#define G_LOG_DOMAIN "JConfig"
+#endif /* G_LOG_DOMAIN */
+
+#include <glib.h>
+
+#include "jiterator.h"
+#include "jconfig.h"
+
+
+
+/*
+ * Defines
+ */
+#define CF_SCAN_WHITESPACE " \t"
+
+
+
+/*
+ * Types
+ */
+typedef struct _JOutputCtxt JOutputCtxt;
+
+
+/*
+ * Structures
+ */
+struct _JConfigCtxt
+{
+ JConfig *cf;
+ JConfigStanza *cfs;
+ gboolean verbose;
+ gboolean error;
+};
+
+struct _JConfigStanza
+{
+ gchar *stanza_name;
+ GHashTable *attrs;
+};
+
+struct _JConfig
+{
+ gchar *filename;
+ GList *stanza_names;
+ GHashTable *stanzas;
+};
+
+struct _JOutputCtxt
+{
+ FILE *output;
+ gboolean success;
+};
+
+
+
+/*
+ * File globals
+ */
+static const GScannerConfig test_config =
+{
+ "" /* cset_skip_characters */,
+ (
+ G_CSET_a_2_z
+ "_0123456789"
+ G_CSET_A_2_Z
+ ) /* cset_identifier_first */,
+ (
+ G_CSET_a_2_z
+ "_0123456789"
+ G_CSET_A_2_Z
+ ) /* cset_identifier_nth */,
+ "" /* cpair_comment_single */,
+ TRUE /* case_sensitive */,
+ FALSE /* skip_comment_multi */,
+ FALSE /* skip_comment_single */,
+ FALSE /* scan_comment_multi */,
+ TRUE /* scan_identifier */,
+ TRUE /* scan_identifier_1char */,
+ FALSE /* scan_identifier_NULL */,
+ TRUE /* scan_symbols */,
+ FALSE /* scan_binary */,
+ FALSE /* scan_octal */,
+ FALSE /* scan_float */,
+ FALSE /* scan_hex */,
+ FALSE /* scan_hex_dollar */,
+ FALSE /* scan_string_sq */,
+ FALSE /* scan_string_dq */,
+ FALSE /* numbers_2_int */,
+ FALSE /* int_2_float */,
+ FALSE /* identifier_2_string */,
+ FALSE /* char_2_token */,
+ TRUE /* symbol_2_token */,
+ FALSE /* scope_0_fallback */
+};
+
+
+
+
+/*
+ * Forward declarations
+ */
+static JConfig *j_config_parse_any(JConfigCtxt *cfc,
+ const gchar *input_name,
+ gint input_fd,
+ const gchar *input_string,
+ gint input_len);
+static void j_config_parse_base(GScanner *scanner, JConfigCtxt *cfc);
+static void j_config_parse_to_eol(GScanner *scanner);
+static void j_config_parse_comment(GScanner *scanner);
+static void j_config_parse_stanza_name(GScanner *scanner,
+ JConfigCtxt *cfc);
+static void j_config_parse_white_start(GScanner *scanner,
+ JConfigCtxt *cfc);
+static void j_config_parse_stanza_attr(GScanner *scanner,
+ JConfigCtxt *cfc);
+static void j_config_foreach_attr_print(gpointer key,
+ gpointer value,
+ gpointer o_ctxt);
+static void j_config_foreach_stanza_print(gpointer key,
+ gpointer value,
+ gpointer o_ctxt);
+static void j_config_attr_names_foreach(gpointer key,
+ gpointer value,
+ gpointer user_data);
+static void j_config_free_stanza(JConfigStanza *cfs);
+static JConfig *j_config_config_new(void);
+static JConfigStanza *j_config_stanza_new(void);
+static void j_config_free_stanza_node(gpointer key,
+ gpointer value,
+ gpointer thrway);
+static void j_config_free_config_node(gpointer key,
+ gpointer value,
+ gpointer thrway);
+static void j_config_free_stanza_proxy(gpointer data, gpointer thrway);
+static void j_config_foreach_attr_append(gpointer key,
+ gpointer value,
+ gpointer fbuffer);
+static void j_config_foreach_stanza_append(gpointer key,
+ gpointer value,
+ gpointer fbuffer);
+
+
+
+/*
+ * Functions
+ */
+
+
+/*
+ * JConfigCtxt *j_config_new_context()
+ *
+ * Returns a new JConfigCtxt.
+ */
+JConfigCtxt *j_config_new_context()
+{
+ JConfigCtxt *cfc;
+
+ cfc = g_new(JConfigCtxt, 1);
+ if (cfc == NULL)
+ {
+ g_warning("Unable to create a JConfigCtxt structure: %s\n",
+ g_strerror(errno));
+ return(NULL);
+ }
+
+ cfc->cfs = NULL;
+ cfc->cf = NULL;
+ cfc->verbose = TRUE;
+ cfc->error = FALSE;
+
+ return cfc;
+} /* j_config_context_new() */
+
+
+/*
+ * void j_config_context_free(JConfigCtxt *cfc)
+ *
+ * Frees a JConfigCtxt. Does *not* free the associated JConfig.
+ */
+void j_config_context_free(JConfigCtxt *cfc)
+{
+ g_return_if_fail(cfc != NULL);
+ g_free(cfc);
+} /* j_config_context_free() */
+
+
+/*
+ * gboolean j_config_context_get_error(JConfigCtxt *cfc)
+ *
+ * Set zero for continuing past errors, nonzero to fail.
+ */
+gboolean j_config_context_get_error(JConfigCtxt *cfc)
+{
+ g_return_val_if_fail(cfc != NULL, TRUE);
+
+ return cfc->error;
+} /* j_config_context_get_error() */
+
+
+/*
+ * void j_config_context_set_verbose(JConfigCtxt *cfc, gboolean verbose)
+ *
+ * Set zero for quiet, nonzero for verbose.
+ */
+void j_config_context_set_verbose(JConfigCtxt *cfc, gboolean verbose)
+{
+ g_return_if_fail(cfc != NULL);
+
+ cfc->verbose = verbose;
+} /* j_config_context_set_verbose() */
+
+
+/*
+ * static JConfig *j_config_parse_any(JConfigCtxt *cfc,
+ * const gchar *input_name,
+ * gint input_fd,
+ * const gchar *input_string,
+ * gint input_len)
+ *
+ * The real initial parsing routine.
+ * Creates the JConfig and structures and then
+ * calls j_config_parse_base();
+ *
+ * some of this is ripped from gtkrc.c
+ */
+static JConfig *j_config_parse_any(JConfigCtxt *cfc,
+ const gchar *input_name,
+ gint input_fd,
+ const gchar *input_string,
+ gint input_len)
+{
+ GScanner *scanner;
+
+ scanner = g_scanner_new((GScannerConfig *)&test_config);
+
+ if (input_fd >= 0)
+ {
+ g_assert(input_string == NULL);
+ g_scanner_input_file(scanner, input_fd);
+ }
+ else
+ {
+ g_assert(input_string != NULL);
+ g_assert(input_len >= 0);
+ g_scanner_input_text(scanner, input_string, input_len);
+ }
+ scanner->input_name = input_name;
+
+ cfc->cf = j_config_config_new();
+ if (cfc->cf == NULL)
+ {
+ if (cfc->verbose)
+ {
+ g_warning("Unable to create a JConfig structure: %s\n",
+ g_strerror(errno));
+ }
+ cfc->error = TRUE;
+ return(NULL);
+ }
+
+ cfc->cf->filename = g_strdup(input_name);
+ j_config_parse_base(scanner, cfc);
+
+ g_scanner_destroy(scanner);
+
+ return(cfc->cf);
+} /* j_config_parse_any() */
+
+
+/*
+ * static void j_config_parse_base(GScanner *scanner, JConfigCtxt *cfc)
+ *
+ * The config file is line oriented. In this scope, it is assumed
+ * that the scanner is situated at the begining of a line _always_.
+ * As such, every sub-function called must return with the scanner
+ * at the beginning of a line (or EOF);
+ *
+ * This function runs through line by line, deciding what
+ * sub-function should handle each line.
+ */
+static void j_config_parse_base(GScanner *scanner, JConfigCtxt *cfc)
+{
+ gboolean done;
+ gchar *toknam;
+ GTokenValue *value;
+
+ value = &scanner->next_value;
+
+ done = FALSE;
+ while (done == FALSE)
+ {
+ GTokenType token;
+
+ token = g_scanner_peek_next_token(scanner);
+
+ switch (token)
+ {
+ case G_TOKEN_EOF:
+ done = TRUE;
+ break;
+ case G_TOKEN_NONE:
+ /* will this ever happen? */
+ break;
+ case G_TOKEN_ERROR:
+ /* should do something here */
+ break;
+ case G_TOKEN_CHAR:
+ if (strchr(CF_SCAN_WHITESPACE, value->v_char) != NULL)
+ j_config_parse_white_start(scanner, cfc);
+ else if (value->v_char == '#')
+ j_config_parse_comment(scanner);
+ else if (value->v_char == '\n')
+ {
+#ifdef DEBUG
+ g_print("Newline\n");
+#endif /* DEBUG */
+ g_scanner_get_next_token(scanner);
+ if (cfc->cfs != NULL)
+ cfc->cfs = NULL;
+ }
+ else
+ {
+ if (cfc->verbose)
+ {
+ g_warning("Invalid character in stanza name: %c\n",
+ value->v_char);
+ }
+ cfc->error = TRUE;
+ j_config_parse_to_eol(scanner);
+ if (cfc->cfs != NULL)
+ cfc->cfs = NULL;
+ }
+ break;
+ case G_TOKEN_SYMBOL:
+ /* Another one I don't think I should get */
+ break;
+ case G_TOKEN_IDENTIFIER:
+ toknam = "G_TOKEN_IDENTIFIER";
+ j_config_parse_stanza_name(scanner, cfc);
+ break;
+ default:
+ toknam = "NONE";
+ if (cfc->verbose)
+ g_warning("Unknown token\n");
+ cfc->error = TRUE;
+ j_config_parse_to_eol(scanner);
+ if (cfc->cfs != NULL)
+ cfc->cfs = NULL;
+ break;
+ }
+ }
+} /* j_config_parse_base() */
+
+
+/*
+ * static void j_config_parse_to_eol(GScanner *scanner)
+ *
+ * This is a simple function that just finds the end of a line,
+ * throwing away anything it sees.
+ */
+static void j_config_parse_to_eol(GScanner *scanner)
+{
+ gboolean done;
+ GTokenType token;
+ GTokenValue *value;
+
+ value = &scanner->value;
+
+ done = FALSE;
+ while (done == FALSE)
+ {
+ token = g_scanner_peek_next_token(scanner);
+ if (token == G_TOKEN_EOF)
+ done = TRUE;
+ else
+ {
+ token = g_scanner_get_next_token(scanner);
+ if ((token = G_TOKEN_CHAR) && (value->v_char == '\n'))
+ done = TRUE;
+ }
+ }
+} /* j_config_parse_to_eol() */
+
+
+/*
+ * static void j_config_parse_comment(GScanner *scanner)
+ *
+ * Parses a comment out of the file, throwing it away.
+ */
+static void j_config_parse_comment(GScanner *scanner)
+{
+ GTokenType token;
+ GTokenValue *value;
+
+ value = &scanner->value;
+ token = g_scanner_get_next_token(scanner);
+
+ g_assert(token == G_TOKEN_CHAR);
+ g_assert(value->v_char == '#');
+
+ j_config_parse_to_eol(scanner);
+
+#ifdef DEBUG
+ g_print("Skipped comment\n");
+#endif /* DEBUG */
+} /* j_config_parse_comment() */
+
+
+/*
+ * static void j_config_parse_stanza_name(GScanner *scanner,
+ * JConfigCtxt *cfc)
+ *
+ * If a line starts with a non-whitespace character, it signifies a
+ * new stanza. Stanza names are defined by the Perl-style regular
+ * expression /^\w+:\s*\n/. Just by virtue of entering this function,
+ * any current stanza is closed.
+ *
+ * The gotos are because I decided it was cleaner than a
+ * g_free() at every error.
+ */
+static void j_config_parse_stanza_name(GScanner *scanner,
+ JConfigCtxt *cfc)
+{
+ gboolean done;
+ gchar *stanza_name;
+ GTokenType token;
+ GTokenValue *value;
+
+ value = &scanner->value;
+ token = g_scanner_get_next_token(scanner);
+
+ g_assert(token == G_TOKEN_IDENTIFIER);
+
+ if (cfc->cfs != NULL)
+ cfc->cfs = NULL;
+
+ stanza_name = g_strdup(value->v_identifier);
+
+ token = g_scanner_peek_next_token(scanner);
+ if (token == G_TOKEN_EOF)
+ {
+ if (cfc->verbose)
+ g_warning("Invalid stanza name declaration: missing ':'\n");
+ cfc->error = TRUE;
+ goto stanza_name_free;
+ }
+
+ token = g_scanner_get_next_token(scanner);
+ if (token != G_TOKEN_CHAR)
+ {
+ if (cfc->verbose)
+ g_warning("Invalid stanza name declaration\n");
+ cfc->error = TRUE;
+ j_config_parse_to_eol(scanner);
+ goto stanza_name_free;
+ }
+ if (value->v_char == '\n')
+ {
+ if (cfc->verbose)
+ g_warning("Invalid stanza name declaration: missing ':'\n");
+ cfc->error = TRUE;
+ goto stanza_name_free;
+ }
+ if (value->v_char != ':')
+ {
+ if (cfc->verbose)
+ {
+ g_warning("Invalid character in stanza name declaration: %c\n",
+ value->v_char);
+ }
+ cfc->error = TRUE;
+ j_config_parse_to_eol(scanner);
+ goto stanza_name_free;
+ }
+
+ done = FALSE;
+ while (done == FALSE)
+ {
+ token = g_scanner_peek_next_token(scanner);
+ if (token == G_TOKEN_EOF)
+ done = TRUE;
+ else if (token == G_TOKEN_CHAR)
+ {
+ token = g_scanner_get_next_token(scanner);
+ if (value->v_char == '\n')
+ done = TRUE;
+ else if (strchr(CF_SCAN_WHITESPACE, value->v_char) == NULL)
+ {
+ if (cfc->verbose)
+ g_warning("Trailing garbage on stanza name declaration\n");
+ cfc->error = TRUE;
+ j_config_parse_to_eol(scanner);
+ goto stanza_name_free;
+ }
+ }
+ else
+ {
+ if (cfc->verbose)
+ g_warning("Trailing garbage on stanza name declaration\n");
+ cfc->error = TRUE;
+ j_config_parse_to_eol(scanner);
+ goto stanza_name_free;
+ }
+ }
+
+ cfc->cfs = j_config_add_stanza(cfc->cf, stanza_name);
+
+#ifdef DEBUG
+ g_print("New stanza: %s\n", stanza_name);
+#endif /* DEBUG */
+
+stanza_name_free:
+ g_free(stanza_name);
+} /* j_config_parse_stanza_name() */
+
+
+/*
+ * static void j_config_parse_white_start(GScanner *scanner,
+ * JConfigCtxt *cfc)
+ *
+ * If a line starts with whitespace, it is either a blank line, or an
+ * attribute line. We skip whitespace lines.
+ * If it looks like an attribute line, we call the proper function.
+ */
+static void j_config_parse_white_start(GScanner *scanner,
+ JConfigCtxt *cfc)
+{
+ gboolean done;
+ GTokenType token;
+ GTokenValue *value;
+
+ value = &scanner->value;
+ token = g_scanner_get_next_token(scanner);
+
+ g_assert(token == G_TOKEN_CHAR);
+ g_assert(strchr(CF_SCAN_WHITESPACE, value->v_char) != NULL);
+
+ done = FALSE;
+ while (done == FALSE)
+ {
+ token = g_scanner_peek_next_token(scanner);
+ switch (token)
+ {
+ case G_TOKEN_EOF:
+ done = TRUE;
+ break;
+ case G_TOKEN_IDENTIFIER:
+ j_config_parse_stanza_attr(scanner, cfc);
+ done = TRUE;
+ break;
+ case G_TOKEN_CHAR:
+ token = g_scanner_get_next_token(scanner);
+ if (value->v_char == '\n')
+ {
+#ifdef DEBUG
+ g_print("Skipped whitespace line\n");
+#endif /* DEBUG */
+ if (cfc->cfs != NULL)
+ cfc->cfs = NULL;
+ done = TRUE;
+ }
+ else if (strchr(CF_SCAN_WHITESPACE, value->v_char) == NULL)
+ {
+ if (cfc->verbose)
+ {
+ g_warning("Invalid character in attribute name: %c\n",
+ value->v_char);
+ }
+ cfc->error = TRUE;
+ j_config_parse_to_eol(scanner);
+ done = TRUE;
+ }
+ break;
+ default:
+ break;
+ }
+ }
+} /* j_config_parse_white_start() */
+
+
+/*
+ * static void j_config_parse_stanza_attr(GScanner *scanner,
+ * JConfigCtxt *cfc)
+ *
+ * An attribute is of the form <attribute name>=<attribute value>.
+ * <attribute name> is defined by the Perl-style regular expression
+ * /^\s+\w+\s* /. Note that the leading whitespace (/^\s+/) has been
+ * stripped by j_config_parse_white_start() already.
+ * <attribute value> is defined as /\s*.*\n/. The leading whitespace
+ * (between the "=" and the first non-whitespace character in
+ * <attribute value>) is stripped, as is the newline.
+ *
+ * This now supports continuation lines. An attribute line ending in
+ * '\<newline>' will cause a <newline> to be entered into the buffer
+ * and the next line will be treated as part of the attribute.
+ */
+static void j_config_parse_stanza_attr(GScanner *scanner,
+ JConfigCtxt *cfc)
+{
+ gboolean done, multi_line;
+ gchar *attr_name;
+ GString *attr_value;
+ GTokenType token;
+ GTokenValue *value;
+
+ enum
+ {
+ CF_STATE_ID,
+ CF_STATE_EQUAL,
+ CF_STATE_VALUE
+ } cur_state;
+
+ value = &scanner->value;
+ token = g_scanner_get_next_token(scanner);
+
+ g_assert(token == G_TOKEN_IDENTIFIER);
+
+ if (cfc->cfs == NULL)
+ {
+ if (cfc->verbose)
+ g_warning("Attributes require a matching stanza\n");
+ cfc->error = TRUE;
+ j_config_parse_to_eol(scanner);
+ return;
+ }
+
+ attr_name = g_strdup(value->v_identifier);
+ attr_value = g_string_new(NULL);
+
+ cur_state = CF_STATE_ID;
+ done = FALSE;
+ multi_line = FALSE;
+ while (done == FALSE)
+ {
+ token = g_scanner_peek_next_token(scanner);
+ if (token == G_TOKEN_EOF)
+ {
+ if (cur_state == CF_STATE_ID)
+ {
+ if (cfc->verbose)
+ g_warning("Invalid attribute: missing '='\n");
+ cfc->error = TRUE;
+ goto attribute_free;
+ }
+ done = TRUE;
+ }
+ else if (token == G_TOKEN_CHAR)
+ {
+ token = g_scanner_get_next_token(scanner);
+ if (value->v_char == '\n')
+ {
+ if (cur_state == CF_STATE_ID)
+ {
+ if (cfc->verbose)
+ g_warning("Invalid attribute: missing '='\n");
+ cfc->error = TRUE;
+ goto attribute_free;
+ }
+ if (multi_line == FALSE)
+ done = TRUE;
+ else
+ {
+ g_string_append_c(attr_value, value->v_char);
+ multi_line = FALSE;
+ }
+ }
+ else if (multi_line == TRUE)
+ {
+ g_string_append_c(attr_value, '\\');
+ multi_line = FALSE;
+
+ if (value->v_char == '\\')
+ multi_line = TRUE;
+ else
+ g_string_append_c(attr_value, value->v_char);
+ }
+ else if (cur_state == CF_STATE_ID)
+ {
+ if (value->v_char == '=')
+ cur_state = CF_STATE_EQUAL;
+ else if (strchr(CF_SCAN_WHITESPACE, value->v_char) == NULL)
+ {
+ if (cfc->verbose)
+ g_warning("Invalid attribute: expecting '='\n");
+ cfc->error = TRUE;
+ j_config_parse_to_eol(scanner);
+ goto attribute_free;
+ }
+ }
+ else if (cur_state == CF_STATE_EQUAL)
+ {
+ if (strchr(CF_SCAN_WHITESPACE, value->v_char) == NULL)
+ {
+ cur_state = CF_STATE_VALUE;
+ if (value->v_char == '\\')
+ multi_line = TRUE;
+ else
+ g_string_append_c(attr_value, value->v_char);
+ }
+ }
+ else
+ {
+ if (value->v_char == '\\')
+ multi_line = TRUE;
+ else
+ g_string_append_c(attr_value, value->v_char);
+ }
+ }
+ else
+ {
+ token = g_scanner_get_next_token(scanner);
+ if (cur_state == CF_STATE_ID)
+ {
+ if (cfc->verbose)
+ g_warning("Invalid attribute: expecting '='\n");
+ cfc->error = TRUE;
+ j_config_parse_to_eol(scanner);
+ return;
+ }
+ else if (cur_state == CF_STATE_EQUAL)
+ cur_state = CF_STATE_VALUE;
+
+ if (token != G_TOKEN_IDENTIFIER)
+ {
+ if (cfc->verbose)
+ g_warning("Error parsing value\n");
+ cfc->error = TRUE;
+ j_config_parse_to_eol(scanner);
+ goto attribute_free;
+ }
+
+ if (multi_line == TRUE)
+ {
+ g_string_append_c(attr_value, '\\');
+ multi_line = FALSE;
+ }
+
+ g_string_append(attr_value, value->v_identifier);
+ }
+ }
+
+
+ j_config_set_attribute(cfc->cfs, attr_name, attr_value->str);
+#ifdef DEBUG
+ g_print("Attribute: \"%s\" = \"%s\"\n", attr_name, attr_value->str);
+#endif /* DEBUG */
+
+attribute_free:
+ g_free(attr_name);
+ g_string_free(attr_value, FALSE);
+}
+
+
+/*
+ * static JConfig *j_config_config_new()
+ *
+ * Allocates a new JConfig structure
+ */
+static JConfig *j_config_config_new()
+{
+ JConfig *cf;
+
+ cf = g_new(JConfig, 1);
+ if (cf == NULL) return(NULL);
+
+ cf->filename = NULL;
+ cf->stanza_names = NULL;
+ cf->stanzas = g_hash_table_new(g_str_hash, g_str_equal);
+ if (cf->stanzas == NULL)
+ {
+ g_free(cf);
+ return(NULL);
+ }
+
+ return(cf);
+} /* j_config_config_new() */
+
+
+/*
+ * static JConfigStanza *j_config_stanza_new()
+ *
+ * Allocates a new JConfigStanza structure
+ */
+static JConfigStanza *j_config_stanza_new()
+{
+ JConfigStanza *cfs;
+
+ cfs = g_new(JConfigStanza, 1);
+ if (cfs == NULL) return(NULL);
+
+ cfs->stanza_name = NULL;
+ cfs->attrs = g_hash_table_new(g_str_hash, g_str_equal);
+ if (cfs->attrs == NULL)
+ {
+ g_free(cfs);
+ return(NULL);
+ }
+
+ return(cfs);
+} /* j_config_stanza_new() */
+
+
+/*
+ * static void j_config_foreach_attr_print(gpointer key,
+ * gpointer value,
+ * gpointer o_ctxt)
+ *
+ * Prints each attribute -> value pair.
+ */
+static void j_config_foreach_attr_print(gpointer key,
+ gpointer value,
+ gpointer o_ctxt)
+{
+ gchar delimiter[2] = {'\n', '\0'};
+ gchar **output_lines;
+ gboolean first_line;
+ gint i, rc;
+ JOutputCtxt *ctxt;
+
+ ctxt = (JOutputCtxt *)o_ctxt;
+ if (ctxt->success == FALSE)
+ return;
+
+ if ((value == NULL) || (((gchar *)value)[0] == '\0'))
+ {
+ rc = fprintf(ctxt->output, "\t%s =\n", (gchar *)key);
+ if (rc < 1)
+ ctxt->success = FALSE;
+ return;
+ }
+
+ output_lines = g_strsplit(value, delimiter, 0);
+ if (output_lines == NULL)
+ {
+#if DEBUG
+ g_warning("Unable to allocate memory for multiline attribute: %s\n",
+ g_strerror(errno));
+#endif
+ ctxt->success = FALSE;
+ return;
+ }
+
+ first_line = TRUE;
+ rc = 0;
+ for (i = 0; output_lines[i] != NULL; i++)
+ {
+ if (first_line == TRUE)
+ {
+ rc = fprintf(ctxt->output, "\t%s = %s",
+ (gchar *)key, output_lines[i]);
+ first_line = FALSE;
+ }
+ else
+ rc = fprintf(ctxt->output, "\\\n%s", output_lines[i]);
+ }
+ g_strfreev(output_lines);
+
+ if (rc < 1)
+ {
+ ctxt->success = FALSE;
+ return;
+ }
+
+ rc = fprintf(ctxt->output, "\n");
+ if (rc < 1)
+ ctxt->success = FALSE;
+} /* j_config_foreach_attr_print() */
+
+
+/*
+ * static void j_config_foreach_stanza_print(gpointer key,
+ * gpointer value,
+ * gpointer o_ctxt)
+ *
+ * Runs through each stanza, printing the header and
+ * calling j_config_foreach_attr_print() on the attributes.
+ */
+static void j_config_foreach_stanza_print(gpointer key,
+ gpointer value,
+ gpointer o_ctxt)
+{
+ gint rc;
+ GList *elem;
+ JConfigStanza *cfs;
+ JOutputCtxt *ctxt;
+
+ elem = (GList *)value;
+ ctxt = (JOutputCtxt *)o_ctxt;
+ if (ctxt->success == FALSE)
+ return;
+
+ while (elem)
+ {
+ cfs = (JConfigStanza *)elem->data;
+ rc = fprintf(ctxt->output, "%s:\n", (gchar *)key);
+ if (rc < 1)
+ {
+ ctxt->success = FALSE;
+ break;
+ }
+
+ g_hash_table_foreach(cfs->attrs, j_config_foreach_attr_print,
+ o_ctxt);
+
+ rc = fprintf(ctxt->output, "\n");
+ if (rc < 1)
+ {
+ ctxt->success = FALSE;
+ break;
+ }
+ elem = g_list_next(elem);
+ }
+} /* j_config_foreach_stanza_print() */
+
+
+/*
+ * gboolean j_config_dump_file(JConfig *cf,
+ * const gchar *o_ctxt)
+ *
+ * Prints the configuration.
+ *
+ * FIXME: This needs to do more work to protect the resulting file from
+ * ENOSPC, etc.
+ */
+gboolean j_config_dump_file(JConfig *cf,
+ const gchar *output_file)
+{
+ gint rc;
+ JOutputCtxt ctxt;
+
+ g_return_val_if_fail(cf != NULL, FALSE);
+ g_return_val_if_fail(output_file != NULL, FALSE);
+
+ ctxt.success = TRUE;
+ if (strcmp(output_file, "-") == 0)
+ ctxt.output = stdout;
+ else
+ ctxt.output = fopen(output_file, "w");
+
+ if (ctxt.output == NULL)
+ {
+#if DEBUG
+ g_warning("Unable to open file \"%s\" for writing: %s\n",
+ output_file,
+ g_strerror(errno));
+#endif
+ return(FALSE);
+ }
+ g_hash_table_foreach(cf->stanzas,
+ j_config_foreach_stanza_print,
+ &ctxt);
+ if (strcmp(output_file, "-") != 0)
+ {
+ rc = fclose(ctxt.output);
+ if (rc != 0)
+ ctxt.success = FALSE;
+ }
+
+ return(ctxt.success);
+} /* j_config_dump_file() */
+
+
+/*
+ * JIterator *j_config_get_stanza_names(JConfig *cf)
+ *
+ * Returns a list of stanzas contained in this config
+ */
+JIterator *j_config_get_stanza_names(JConfig *cf)
+{
+ g_return_val_if_fail(cf != NULL, NULL);
+
+ return(j_iterator_new_from_list(cf->stanza_names));
+} /* j_config_get_stanza_names() */
+
+
+/*
+ * JConfigStanza *j_config_get_stanza_nth(JConfig *cf,
+ * const gchar *stanza_name,
+ * guint n)
+ *
+ * Retreives the nth stanza with the given name, or NULL if
+ * that does not exist
+ */
+JConfigStanza *j_config_get_stanza_nth(JConfig *cf,
+ const gchar *stanza_name,
+ guint n)
+{
+ JConfigStanza *cfs;
+ GList *elem;
+
+ g_return_val_if_fail(cf != NULL, NULL);
+ g_return_val_if_fail(stanza_name != NULL, NULL);
+
+ elem = g_hash_table_lookup(cf->stanzas, stanza_name);
+ if (elem == NULL)
+ return(NULL);
+
+ elem = g_list_nth(elem, n);
+ cfs = elem != NULL ? (JConfigStanza *)elem->data : NULL;
+
+ return(cfs);
+} /* j_config_get_stanza_nth() */
+
+
+/*
+ * gchar *j_config_get_stanza_name(JConfigStanza *cfs)
+ *
+ * Returns the stanza's name
+ */
+gchar *j_config_get_stanza_name(JConfigStanza *cfs)
+{
+ g_return_val_if_fail(cfs != NULL, NULL);
+
+ return(g_strdup(cfs->stanza_name));
+} /* j_config_get_stanza_name() */
+
+
+/*
+ * JConfigStanza *j_config_add_stanza(JConfig *cf,
+ * const gchar *stanza_name);
+ *
+ * Adds a new stanza to the configuration structure
+ */
+JConfigStanza *j_config_add_stanza(JConfig *cf,
+ const gchar *stanza_name)
+{
+ JConfigStanza *cfs;
+ GList *elem;
+
+ g_return_val_if_fail(cf != NULL, NULL);
+ g_return_val_if_fail(stanza_name != NULL, NULL);
+
+ cfs = j_config_stanza_new();
+ if (cfs == NULL)
+ {
+#if DEBUG
+ g_warning("Unable to allocate memory for a new stanza: %s\n",
+ g_strerror(errno));
+#endif
+ return NULL;
+ }
+
+ cfs->stanza_name = g_strdup(stanza_name);
+ elem = (GList *)g_hash_table_lookup(cf->stanzas, stanza_name);
+ if (elem == NULL)
+ {
+ cf->stanza_names =
+ g_list_append(cf->stanza_names, g_strdup(stanza_name));
+ elem = g_list_append(NULL, cfs);
+ g_hash_table_insert(cf->stanzas,
+ g_strdup(stanza_name),
+ elem);
+ }
+ else
+ g_list_append(elem, cfs);
+
+ return(cfs);
+} /* j_config_add_stanza() */
+
+
+/*
+ * void j_config_delete_stanza(JConfig *cf,
+ * JConfigStanza *cfs)
+ *
+ * Removes the stanza pointed to by cfs from the configuration.
+ */
+void j_config_delete_stanza(JConfig *cf,
+ JConfigStanza *cfs)
+{
+ GList *elem, *new_elem;
+ gpointer orig_key;
+ gchar *orig_data;
+
+ g_return_if_fail(cf != NULL);
+ g_return_if_fail(cfs != NULL);
+
+ elem = (GList *)g_hash_table_lookup(cf->stanzas, cfs->stanza_name);
+ if (elem == NULL)
+ {
+#if DEBUG
+ g_warning("Unable to remove stanza - no such class: %s\n",
+ cfs->stanza_name);
+#endif
+ return;
+ }
+
+ new_elem = g_list_remove(elem, cfs);
+ if (elem == NULL)
+ {
+ if (g_hash_table_lookup_extended(cf->stanzas,
+ cfs->stanza_name,
+ &orig_key,
+ NULL))
+ {
+ g_hash_table_remove(cf->stanzas, cfs->stanza_name);
+ g_free(orig_key);
+ }
+
+ elem = cf->stanza_names;
+ while (elem != NULL)
+ {
+ orig_data = (gchar *)elem->data;
+ if (strcmp(cfs->stanza_name, orig_data) == 0)
+ {
+ cf->stanza_names =
+ g_list_remove(cf->stanza_names, elem->data);
+ g_free(orig_data);
+ break;
+ }
+ elem = g_list_next(elem);
+ }
+ }
+ else if (elem != new_elem)
+ {
+ if (g_hash_table_lookup_extended(cf->stanzas,
+ cfs->stanza_name,
+ &orig_key,
+ NULL))
+ {
+ g_hash_table_remove(cf->stanzas, cfs->stanza_name);
+ g_free(orig_key);
+ }
+ g_hash_table_insert(cf->stanzas,
+ g_strdup(cfs->stanza_name),
+ new_elem);
+ }
+
+ j_config_free_stanza(cfs);
+} /* j_config_delete_stanza() */
+
+
+/*
+ * void j_config_delete_stanza_nth(JConfig *cf,
+ * const gchar *stanza_name,
+ * guint n)
+ *
+ * Removes the nth stanza of class stanza_name from the
+ * configuration.
+ */
+void j_config_delete_stanza_nth(JConfig *cf,
+ const gchar *stanza_name,
+ guint n)
+{
+ JConfigStanza *cfs;
+
+ g_return_if_fail(cf != NULL);
+ g_return_if_fail(stanza_name != NULL);
+
+ cfs = j_config_get_stanza_nth(cf, stanza_name, n);
+ if (cfs == NULL)
+ return;
+
+ j_config_delete_stanza(cf, cfs);
+} /* j_config_delete_stanza() */
+
+
+/*
+ * JConfig *j_config_parse_file_with_context(JConfigCtxt *cfc,
+ * const gchar *filename)
+ *
+ * Parses a config file
+ */
+JConfig *j_config_parse_file_with_context(JConfigCtxt *cfc,
+ const gchar *filename)
+{
+ gint fd;
+ JConfig *cf;
+
+ g_return_val_if_fail(cfc != NULL, NULL);
+ g_return_val_if_fail(filename != NULL, NULL);
+
+ if (strcmp(filename, "-") == 0)
+ fd = STDIN_FILENO;
+ else
+ fd = open(filename, O_RDONLY);
+
+ if (fd < 0)
+ {
+ if (cfc->verbose)
+ {
+ g_warning("Unable to open file \"%s\": %s\n",
+ filename,
+ g_strerror(errno));
+ }
+ cfc->error = TRUE;
+ return(NULL);
+ }
+
+ cf = j_config_parse_any(cfc, filename, fd, NULL, 0);
+
+ if (strcmp(filename, "-") != 0)
+ close(fd);
+
+ return(cf);
+} /* j_config_parse_file_with_context() */
+
+
+/*
+ * JConfig *j_config_parse_file(const gchar *filename)
+ *
+ * Parses a config file, creating the context.
+ */
+JConfig *j_config_parse_file(const gchar *filename)
+{
+ JConfigCtxt *cfc;
+ JConfig *cf = NULL;
+
+ cfc = j_config_new_context();
+ if (cfc)
+ {
+ cf = j_config_parse_file_with_context(cfc, filename);
+ j_config_context_free(cfc);
+ }
+
+ return(cf);
+} /* j_config_parse_file() */
+
+
+/*
+ * JConfig *j_config_parse_memory_with_context(JConfigCtxt *cfc,
+ * gchar *buffer,
+ * gint buf_len)
+ *
+ * Parses a config from a text buffer
+ */
+JConfig *j_config_parse_memory_with_context(JConfigCtxt *cfc,
+ gchar *buffer,
+ gint buf_len)
+{
+ JConfig *cf;
+
+ g_return_val_if_fail(cfc != NULL, NULL);
+ g_return_val_if_fail(buffer != NULL, NULL);
+
+ if (buf_len < 0)
+ buf_len = 0;
+
+ cf = j_config_parse_any(cfc, "memory", -1, buffer, buf_len);
+
+ return(cf);
+} /* j_config_parse_memory() */
+
+
+/*
+ * JConfig *j_config_parse_memory(gchar *buffer, gint buf_len)
+ *
+ * Parses a buffer, creating the context.
+ */
+JConfig *j_config_parse_memory(gchar *buffer, gint buf_len)
+{
+ JConfigCtxt *cfc;
+ JConfig *cf = NULL;
+
+ cfc = j_config_new_context();
+ if (cfc)
+ {
+ cf = j_config_parse_memory_with_context(cfc, buffer, buf_len);
+ j_config_context_free(cfc);
+ }
+
+ return(cf);
+} /* j_config_parse_file() */
+
+
+/*
+ * JConfigMatch *j_config_match_build(guint num_matches, ...)
+ *
+ * Convenience function to build an array of JConfigMatch structures.
+ * num_matches is the number of key, value pairs passed to this
+ * function. The number of varargs passed should therefore be double
+ * num_matches. eg:
+ *
+ * j_config_match_build(2, "foo", "bar", "quuz", "quuuz");
+ *
+ * This function builds a match that requires:
+ *
+ * foo = bar
+ * quuz = quuuz
+ *
+ * Strings passed in are *NOT* copied. They are merely referenced.
+ * Because of this, the returned array of JConfigMatch structures can
+ * be freed with g_free(). The caller must take care not to change or
+ * destroy the referened strings until they are done with the
+ * array of JConfigMatch structures.
+ */
+JConfigMatch *j_config_match_build(guint num_matches, ...)
+{
+ guint i;
+ va_list args;
+ JConfigMatch *matches;
+
+ matches = g_new0(JConfigMatch, num_matches);
+
+ va_start(args, num_matches);
+ for (i = 0; i < num_matches; i++)
+ {
+ matches[i].type = J_CONFIG_MATCH_VALUE;
+ matches[i].name = va_arg(args, gchar *);
+ if (matches[i].name == NULL)
+ {
+ g_free(matches);
+ matches = NULL;
+ break;
+ }
+ matches[i].value = va_arg(args, gchar *);
+ }
+ va_end(args);
+
+ return(matches);
+} /* j_config_match_build() */
+
+
+/*
+ * JIterator *j_config_get_stanzas(JConfig *cf,
+ * const gchar *stanza_name,
+ * JConfigMatch *matches,
+ * guint num_matches)
+ *
+ * Gets the list of stanzas with a given name. Optionally
+ * return only those that staitisfy matches. matches is an array
+ * of JConfigMatch structures. num_matches describes the number
+ * of items in the array. This array can be built by the caller
+ * explicitly, or the caller can use the convenience function
+ * j_config_match_build(). If num_matches is 0, matches can be
+ * NULL.
+ */
+JIterator *j_config_get_stanzas(JConfig *cf,
+ const gchar *stanza_name,
+ JConfigMatch *matches,
+ guint num_matches)
+{
+ gint i;
+ JConfigStanza *cfs;
+ gchar *value;
+ GList *elem, *tmp;
+ JIterator *iter;
+
+ g_return_val_if_fail(cf != NULL, NULL);
+ g_return_val_if_fail(stanza_name != NULL, NULL);
+ g_return_val_if_fail((num_matches == 0) || (matches != NULL), NULL);
+
+ elem = (GList *)g_hash_table_lookup(cf->stanzas, stanza_name);
+
+ if (num_matches > 0)
+ {
+ tmp = NULL;
+ for (; elem != NULL; elem = g_list_next(elem))
+ {
+ cfs = (JConfigStanza *)elem->data;
+ g_assert(cfs != NULL);
+
+ for (i = 0; i < num_matches; i++)
+ {
+ g_assert(matches[i].name != NULL);
+ value = j_config_get_attribute(cfs, matches[i].name);
+ if (value != NULL)
+ {
+ if (matches[i].value == NULL)
+ {
+ if (value[0] != '\0')
+ {
+ g_free(value);
+ break;
+ }
+ }
+ else if (strcmp(value, matches[i].value) != 0)
+ {
+ g_free(value);
+ break;
+ }
+ g_free(value);
+ }
+ else
+ {
+ if (matches[i].value != '\0')
+ break;
+ }
+ }
+ if (i >= num_matches) /* All tests succeeded */
+ tmp = g_list_prepend(tmp, cfs);
+ }
+ elem = g_list_reverse(tmp);
+
+ iter = j_iterator_new_from_list(elem);
+ g_list_free(elem);
+ }
+ else
+ iter = j_iterator_new_from_list(elem);
+
+ return(iter);
+} /* j_config_get_stanzas() */
+
+
+/*
+ * void j_config_set_attribute(JConfigStanza *cfs,
+ * const gchar *attr_name,
+ * const gchar *attr_value)
+ *
+ * Sets the value of a given attribute name
+ */
+void j_config_set_attribute(JConfigStanza *cfs,
+ const gchar *attr_name,
+ const gchar *attr_value)
+{
+ g_return_if_fail(cfs != NULL);
+ g_return_if_fail(attr_name != NULL);
+
+ j_config_delete_attribute(cfs, attr_name);
+ g_hash_table_insert(cfs->attrs,
+ g_strdup(attr_name),
+ g_strdup(attr_value));
+} /* j_config_set_attribute() */
+
+
+/*
+ * static void j_config_attr_names_foreach(gpointer key,
+ * gpointer value,
+ * gpointer user_data)
+ *
+ * Foreach function to build the attribute names list.
+ */
+static void j_config_attr_names_foreach(gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ GList **list = (GList **)user_data;
+
+ *list = g_list_append(*list, key);
+} /* j_config_attr_names_foreach() */
+
+
+/*
+ * JIterator *j_config_get_attribute_names(JConfigStanza *cfs)
+ *
+ * Returns an iterator over every attribute name in the stanza.
+ */
+JIterator *j_config_get_attribute_names(JConfigStanza *cfs)
+{
+ JIterator *iter;
+ GList *attr_names = NULL;
+
+ g_return_val_if_fail(cfs != NULL, NULL);
+
+ g_hash_table_foreach(cfs->attrs, j_config_attr_names_foreach,
+ &attr_names);
+
+ iter = j_iterator_new_from_list(attr_names);
+ g_list_free(attr_names);
+
+ return(iter);
+} /* j_config_get_attribute_names() */
+
+
+/*
+ * gchar *j_config_get_attribute(JConfigStanza *cfs,
+ * const gchar *attr_name)
+ *
+ * Retrieves the value of a given attribute name
+ */
+gchar *j_config_get_attribute(JConfigStanza *cfs,
+ const gchar *attr_name)
+{
+ gchar *s;
+
+ g_return_val_if_fail(cfs != NULL, NULL);
+ g_return_val_if_fail(attr_name != NULL, NULL);
+
+ s = (gchar *)g_hash_table_lookup(cfs->attrs, attr_name);
+ s = g_strdup(s);
+
+ return(s);
+} /* j_config_get_attribute() */
+
+
+/*
+ * void j_config_delete_attribute(JConfigStanza *cfs,
+ * const gchar *attr_name)
+ *
+ * Removes the attribute attr_name from the stanza pointed to
+ * by cfs.
+ */
+void j_config_delete_attribute(JConfigStanza *cfs,
+ const gchar *attr_name)
+{
+ gpointer orig_key, orig_value;
+
+ g_return_if_fail(cfs != NULL);
+ g_return_if_fail(attr_name != NULL);
+
+ if (g_hash_table_lookup_extended(cfs->attrs,
+ attr_name,
+ &orig_key,
+ &orig_value))
+ {
+ g_hash_table_remove(cfs->attrs,
+ attr_name);
+ g_free(orig_key);
+ g_free(orig_value);
+ }
+} /* j_config_delete_attribute() */
+
+
+/*
+ * static void j_config_free_stanza_node(gpointer key,
+ * gpointer value,
+ * gpointer thrway)
+ *
+ * Removes a node from a stanza
+ */
+static void j_config_free_stanza_node(gpointer key,
+ gpointer value,
+ gpointer thrway)
+{
+ g_free(key);
+ g_free(value);
+} /* j_config_free_stanza_node() */
+
+
+/*
+ * static void j_config_free_stanza(JConfigStanza *cfs)
+ *
+ * Clears a config file stanza
+ */
+static void j_config_free_stanza(JConfigStanza *cfs)
+{
+ g_return_if_fail(cfs != NULL);
+
+ g_hash_table_foreach(cfs->attrs, j_config_free_stanza_node, NULL);
+ g_hash_table_destroy(cfs->attrs);
+ g_free(cfs->stanza_name);
+ g_free(cfs);
+} /* j_config_free_stanza() */
+
+
+/*
+ * static void j_config_free_stanza_proxy(gpointer data,
+ * gpointer thrway)
+ *
+ * A proxy to call j_config_free_stanza() as a GFunc()
+ */
+static void j_config_free_stanza_proxy(gpointer elem_data,
+ gpointer thrway)
+{
+ j_config_free_stanza(elem_data);
+} /* j_config_free_stanza_proxy() */
+
+
+/*
+ * static void j_config_free_config_node(gpointer key,
+ * gpointer value,
+ * gpointer thrway)
+ *
+ * Removes a node from a config
+ */
+static void j_config_free_config_node(gpointer key,
+ gpointer value,
+ gpointer thrway)
+{
+ GList *elem;
+
+ elem = (GList *)value;
+ g_list_foreach(elem, j_config_free_stanza_proxy, NULL);
+ g_list_free(elem);
+ g_free(key);
+} /* j_config_free_config_node() */
+
+
+/*
+ * void j_config_free(JConfig *cf)
+ *
+ * Deletes a config file tree
+ */
+void j_config_free(JConfig *cf)
+{
+ g_return_if_fail(cf != NULL);
+
+ g_hash_table_foreach(cf->stanzas, j_config_free_config_node, NULL);
+ g_hash_table_destroy(cf->stanzas);
+ g_free(cf->filename);
+ g_free(cf);
+} /* j_config_free() */
+
+
+/*
+ * static void j_config_foreach_attr_append(gpointer key,
+ * gpointer value,
+ * gpointer fbuffer)
+ *
+ * Prints each attribute -> value pair.
+ */
+static void j_config_foreach_attr_append(gpointer key,
+ gpointer value,
+ gpointer fbuffer)
+{
+ gchar delimiter[2] = {'\n', '\0'};
+ gchar **output_lines;
+ gboolean first_line;
+ gint i;
+ GString *buffer;
+
+ g_return_if_fail(fbuffer != NULL);
+
+ buffer = (GString *)fbuffer;
+
+ if ((value == NULL) || (((gchar *)value)[0] == '\0'))
+ {
+ g_string_append_printf(buffer, "\t%s =\n", (gchar *)key);
+ return;
+ }
+
+ output_lines = g_strsplit(value, delimiter, 0);
+ if (output_lines == NULL)
+ {
+ g_warning("Unable to allocate memory for multiline attribute: %s\n",
+ g_strerror(errno));
+ return;
+ }
+
+ first_line = TRUE;
+ for (i = 0; output_lines[i] != NULL; i++)
+ {
+ if (first_line == TRUE)
+ {
+ g_string_append_printf(buffer, "\t%s = %s",
+ (gchar *)key, output_lines[i]);
+ first_line = FALSE;
+ }
+ else
+ g_string_append_printf(buffer, "\\\n%s", output_lines[i]);
+ }
+ g_string_append_printf(buffer, "\n");
+
+ g_strfreev(output_lines);
+} /* j_config_foreach_attr_append() */
+
+
+/*
+ * static void j_config_foreach_stanza_append(gpointer key,
+ * gpointer value,
+ * gpointer fbuffer)
+ *
+ * Runs through each stanza, printing the header and
+ * calling j_config_foreach_attr_append() on the attributes.
+ */
+static void j_config_foreach_stanza_append(gpointer key,
+ gpointer value,
+ gpointer fbuffer)
+{
+ GList *elem;
+ JConfigStanza *cfs;
+ GString *buffer;
+
+ g_return_if_fail(fbuffer != NULL);
+
+ buffer = (GString *)fbuffer;
+ elem = (GList *)value;
+
+ while (elem)
+ {
+ cfs = (JConfigStanza *)elem->data;
+ g_string_append_printf(buffer, "%s:\n", (gchar *)key);
+ g_hash_table_foreach(cfs->attrs, j_config_foreach_attr_append,
+ fbuffer);
+ g_string_append(buffer, "\n");
+ elem = g_list_next(elem);
+ }
+} /* j_config_foreach_stanza_append() */
+
+
+/*
+ * gchar *j_config_dump_memory(JConfig *cf)
+ *
+ * Prints the configuration to an in-memory string.
+ */
+gchar *j_config_dump_memory(JConfig *cf)
+{
+ gchar *output_text;
+ GString *output;
+
+ g_return_val_if_fail(cf != NULL, FALSE);
+
+ output = g_string_new(NULL);
+ if (output == NULL)
+ return(NULL);
+ g_hash_table_foreach(cf->stanzas,
+ j_config_foreach_stanza_append,
+ (gpointer)output);
+
+ output_text = output->str;
+ g_string_free(output, FALSE);
+ return(output_text);
+} /* j_config_dump_memory() */
+
Added: trunk/clusterbo/jconfig.h
===================================================================
--- trunk/clusterbo/jconfig.h 2004-12-14 23:50:34 UTC (rev 489)
+++ trunk/clusterbo/jconfig.h 2004-12-14 23:59:14 UTC (rev 490)
@@ -0,0 +1,103 @@
+/*
+ * jconfig.h
+ *
+ * Header file for configuration file parser
+ *
+ * Copyright (C) 2002 Joel Becker <jlbec at evilplan.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+
+#ifndef __JCONFIG_H
+#define __JCONFIG_H
+
+
+
+/*
+ * Type definitions
+ */
+typedef struct _JConfigStanza JConfigStanza;
+typedef struct _JConfig JConfig;
+typedef struct _JConfigMatch JConfigMatch;
+typedef struct _JConfigCtxt JConfigCtxt;
+
+
+
+/*
+ * Enums
+ */
+typedef enum _JConfigMatchType
+{
+ J_CONFIG_MATCH_VALUE = 0,
+} JConfigMatchType;
+
+
+
+/*
+ * Structures
+ */
+struct _JConfigMatch
+{
+ JConfigMatchType type;
+ gchar *name;
+ gchar *value;
+};
+
+
+
+/*
+ * Functions
+ */
+
+JConfig *j_config_parse_file(const gchar *filename);
+JConfig *j_config_parse_memory(gchar *buffer, gint buf_len);
+JConfigCtxt *j_config_new_context(void);
+void j_config_context_free(JConfigCtxt *cfc);
+void j_config_context_set_verbose(JConfigCtxt *cfc, gboolean verbose);
+gboolean j_config_context_get_error(JConfigCtxt *cfc);
+JConfig *j_config_parse_file_with_context(JConfigCtxt *cfc,
+ const gchar *filename);
+JConfig *j_config_parse_memory_with_context(JConfigCtxt *cfc,
+ gchar *buffer,
+ gint buf_len);
+JIterator *j_config_get_stanza_names(JConfig *cf);
+JConfigMatch *j_config_match_build(guint num_matches, ...);
+JIterator *j_config_get_stanzas(JConfig *cf,
+ const gchar *stanza_name,
+ JConfigMatch *matches,
+ guint num_matches);
+JConfigStanza *j_config_get_stanza_nth(JConfig *cf,
+ const gchar *stanza_name,
+ guint n);
+gchar *j_config_get_stanza_name(JConfigStanza *cfs);
+JConfigStanza *j_config_add_stanza(JConfig *cf,
+ const gchar *stanza_name);
+void j_config_delete_stanza(JConfig *cf, JConfigStanza *cfs);
+void j_config_delete_stanza_nth(JConfig *cf,
+ const gchar *stanza_name,
+ guint n);
+JIterator *j_config_get_attribute_names(JConfigStanza *cfs);
+gchar *j_config_get_attribute(JConfigStanza *cfs,
+ const gchar *attr_name);
+void j_config_set_attribute(JConfigStanza *cfs,
+ const gchar *attr_name,
+ const gchar *attr_value);
+void j_config_delete_attribute(JConfigStanza *cfs,
+ const gchar *attr_name);
+gboolean j_config_dump_file(JConfig *cf, const gchar *output_file);
+gchar *j_config_dump_memory(JConfig *cf);
+void j_config_free(JConfig *cf);
+
+#endif /* __JCONFIG_H */
Added: trunk/clusterbo/jiterator.c
===================================================================
--- trunk/clusterbo/jiterator.c 2004-12-14 23:50:34 UTC (rev 489)
+++ trunk/clusterbo/jiterator.c 2004-12-14 23:59:14 UTC (rev 490)
@@ -0,0 +1,179 @@
+/*
+ * jiterator.c
+ *
+ * Code for opaque iterators.
+ *
+ * Copyright (C) 2001 Oracle Corporation, Joel Becker
+ * <joel.becker at oracle.com>
+ * All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have recieved a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+
+/*
+ * MT safe
+ */
+
+#include <sys/types.h>
+#include <glib.h>
+
+#include "jiterator.h"
+
+
+/* Structures
+ */
+struct _JIterator
+{
+ gpointer context;
+ JIteratorFunc has_more_func;
+ JIteratorFunc get_next_func;
+ GDestroyNotify notify_func;
+};
+
+
+static gpointer j_iterator_list_has_more (gpointer context);
+static gpointer j_iterator_list_get_next (gpointer context);
+static void j_iterator_list_destroy_notify (gpointer context);
+
+
+
+/* Enumerations
+ */
+JIterator*
+j_iterator_new (gpointer context,
+ JIteratorFunc has_more_func,
+ JIteratorFunc get_next_func,
+ GDestroyNotify notify_func)
+{
+ JIterator *iterator;
+
+ iterator = g_new (JIterator, 1);
+ iterator->context = context;
+ iterator->has_more_func = has_more_func;
+ iterator->get_next_func = get_next_func;
+ iterator->notify_func = notify_func;
+
+ return iterator;
+} /* j_iterator_new() */
+
+JIterator*
+j_iterator_new_from_list (GList *init_list)
+{
+ JIterator *iterator;
+ GList *list_copy, *header;
+
+ /* The list is copied here, the caller is responsible for the
+ * data items. On _free(), the list is removed and the data items
+ * left alone. If the caller wants different semantics, the
+ * caller can specify their own functions with _new() */
+ list_copy = g_list_copy(init_list);
+
+ /* This is a header element to refer to the list */
+ header = g_list_prepend(NULL, (gpointer) list_copy);
+
+ iterator = j_iterator_new ((gpointer) header,
+ j_iterator_list_has_more,
+ j_iterator_list_get_next,
+ j_iterator_list_destroy_notify);
+
+ return(iterator);
+} /* j_iterator_new_from_list() */
+
+gboolean
+j_iterator_has_more (JIterator *iterator)
+{
+ gpointer result;
+
+ g_return_val_if_fail (iterator != NULL, FALSE);
+
+ result = (*iterator->has_more_func) (iterator->context);
+
+ return (gboolean) result;
+} /* j_iterator_has_more() */
+
+gpointer
+j_iterator_get_next (JIterator *iterator)
+{
+ gpointer result;
+
+ g_return_val_if_fail (iterator != NULL, NULL);
+
+ result = (*iterator->get_next_func) (iterator->context);
+
+ return result;
+} /* j_iterator_get_next() */
+
+void
+j_iterator_free (JIterator *iterator)
+{
+ (*iterator->notify_func) (iterator->context);
+
+ g_free(iterator);
+} /* j_iterator_free() */
+
+static gpointer
+j_iterator_list_has_more (gpointer context)
+{
+ GList *header, *elem;
+ gboolean result;
+
+ g_return_val_if_fail (context != NULL, (gpointer) FALSE);
+
+ header = (GList *) context;
+ elem = (GList *) header->data;
+
+ result = (elem != NULL);
+
+ return (gpointer) result;
+} /* j_iterator_list_has_more() */
+
+static gpointer
+j_iterator_list_get_next (gpointer context)
+{
+ GList *header, *elem;
+ gpointer result;
+
+ g_return_val_if_fail(context != NULL, NULL);
+
+ header = (GList *) context;
+ elem = (GList *) header->data;
+
+ /* User should have called has_more() */
+ g_return_val_if_fail(elem != NULL, NULL);
+
+ result = elem->data;
+
+ header->data = (gpointer) g_list_next(elem);
+
+ g_list_free_1(elem);
+
+ return result;
+} /* j_iterator_list_get_next() */
+
+static void
+j_iterator_list_destroy_notify (gpointer context)
+{
+ GList *header, *elem;
+
+ g_return_if_fail (context != NULL);
+
+ header = (GList *) context;
+ elem = (GList *) header->data;
+
+ g_list_free(elem); /* NULL if at end of list */
+
+ g_list_free(header);
+} /* j_iterator_list_destroy_notify() */
Added: trunk/clusterbo/jiterator.h
===================================================================
--- trunk/clusterbo/jiterator.h 2004-12-14 23:50:34 UTC (rev 489)
+++ trunk/clusterbo/jiterator.h 2004-12-14 23:59:14 UTC (rev 490)
@@ -0,0 +1,42 @@
+/*
+ * jiterator.h
+ *
+ * Prototypes for JIterator
+ *
+ * Copyright (C) 2002 Joel Becker <jlbec at evilplan.org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License version 2 as published by the Free Software Foundation.
+ *
+ * This library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the Free
+ * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#ifndef __JITERATOR_H
+#define __JITERATOR_H
+
+
+/* Typedefs */
+typedef struct _JIterator JIterator;
+typedef gpointer (*JIteratorFunc) (gpointer context);
+
+
+/* Functions */
+JIterator* j_iterator_new(gpointer context,
+ JIteratorFunc has_more_func,
+ JIteratorFunc get_next_func,
+ GDestroyNotify notify_func);
+JIterator* j_iterator_new_from_list(GList *init_list);
+gboolean j_iterator_has_more(JIterator *iterator);
+gpointer j_iterator_get_next(JIterator *iterator);
+void j_iterator_free(JIterator *iterator);
+
+#endif /* __JITERATOR_H */
+
Modified: trunk/configure.in
===================================================================
--- trunk/configure.in 2004-12-14 23:50:34 UTC (rev 489)
+++ trunk/configure.in 2004-12-14 23:59:14 UTC (rev 490)
@@ -192,6 +192,7 @@
AC_OUTPUT([
Config.make
libocfs2/ocfs2_err.et
+libo2cb/o2cb_err.et
debugfs.ocfs2/debugfs.ocfs2.8
mkfs.ocfs2/mkfs.ocfs2.8
fsck.ocfs2/fsck.ocfs2.8
Property changes on: trunk/libo2cb
___________________________________________________________________
Name: svn:ignore
+ .*.sw?
*.d
debug_*
o2cb_err.c
o2cb_err.h
o2cb_err.et
cscope*
libo2cb.a
Added: trunk/libo2cb/Makefile
===================================================================
--- trunk/libo2cb/Makefile 2004-12-14 23:50:34 UTC (rev 489)
+++ trunk/libo2cb/Makefile 2004-12-14 23:59:14 UTC (rev 490)
@@ -0,0 +1,83 @@
+TOPDIR = ..
+
+include $(TOPDIR)/Preamble.make
+
+WARNINGS = -Wall -Wstrict-prototypes -Wmissing-prototypes \
+ -Wmissing-declarations
+
+ifdef OCFS_DEBUG
+OPTS += -ggdb
+else
+OPTS += -O2
+endif
+
+INCLUDES = -Iinclude
+
+LIBRARIES = libo2cb.a
+
+CFLAGS = $(OPTS) $(WARNINGS) -fPIC
+CPPFLAGS += -DO2CB_FLAT_INCLUDES
+
+ifneq ($(OCFS2_DEBUG_EXE),)
+DEBUG_EXE_FILES = $(shell awk '/DEBUG_EXE/{if (k[FILENAME] == 0) {print FILENAME; k[FILENAME] = 1;}}' $(CFILES))
+DEBUG_EXE_PROGRAMS = $(addprefix debug_,$(subst .c,,$(DEBUG_EXE_FILES)))
+
+.SECONDARY:
+
+UNINST_PROGRAMS += $(DEBUG_EXE_PROGRAMS)
+
+debug_%.o : %.c
+ $(CC) $(CFLAGS) $(LOCAL_CFLAGS) $(CPPFLAGS) $(LOCAL_CPPFLAGS) \
+ $(INCLUDES) $(DEFINES) \
+ -DDEBUG_EXE -o $@ -c $<
+
+debug_%: debug_%.o libo2cb.a
+ $(LINK) $(COM_ERR_LIBS)
+
+endif
+
+CFILES = \
+ o2cb_abi.c
+
+HFILES = \
+ include/ocfs2_heartbeat.h \
+ include/ocfs2_nodemanager.h \
+ include/ocfs2_tcp.h.h \
+ include/o2cb_abi.h \
+ include/o2cb.h
+
+HFILES_GEN = \
+ include/o2cb_err.h
+
+$(CFILES): $(HFILES_GEN)
+
+OBJS = $(subst .c,.o,$(CFILES)) \
+ o2cb_err.o
+
+o2cb_err.et: o2cb_err.et.in
+ cd $(TOPDIR) && ./config.status
+
+include/o2cb_err.h: o2cb_err.h
+ cp $< $@
+
+o2cb_err.c o2cb_err.h: o2cb_err.et
+ compile_et o2cb_err.et
+
+libo2cb.a: $(OBJS)
+ rm -f $@
+ $(AR) r $@ $^
+ $(RANLIB) $@
+
+DIST_FILES = $(CFILES) $(HFILES) o2cb_err.et.in
+
+DIST_RULES = dist-subdircreate
+
+dist-subdircreate:
+ $(TOPDIR)/mkinstalldirs $(DIST_DIR)/include
+
+CLEAN_RULES = clean-err
+
+clean-err:
+ rm -f o2cb_err.c o2cb_err.h include/o2cb_err.h
+
+include $(TOPDIR)/Postamble.make
Property changes on: trunk/libo2cb/include
___________________________________________________________________
Name: svn:ignore
+ .*.sw?
o2cb_err.h
Added: trunk/libo2cb/include/o2cb.h
===================================================================
--- trunk/libo2cb/include/o2cb.h 2004-12-14 23:50:34 UTC (rev 489)
+++ trunk/libo2cb/include/o2cb.h 2004-12-14 23:59:14 UTC (rev 490)
@@ -0,0 +1,58 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * o2cb.h
+ *
+ * Routines for accessing the o2cb configuration.
+ *
+ * Copyright (C) 2004 Oracle. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+
+#ifndef _O2CB_H
+#define _O2CB_H
+
+#ifndef _XOPEN_SOURCE
+# define _XOPEN_SOURCE 600
+#endif
+#ifndef _LARGEFILE64_SOURCE
+# define _LARGEFILE64_SOURCE
+#endif
+
+#include <stdio.h>
+#include <stdint.h>
+#include <sys/stat.h>
+#include <time.h>
+
+#include <linux/types.h>
+
+#include <et/com_err.h>
+
+#if O2CB_FLAT_INCLUDES
+#include "o2cb_err.h"
+
+#include "ocfs2_heartbeat.h"
+#include "ocfs2_nodemanager.h"
+#include "ocfs2_tcp.h"
+#else
+#include <o2cb/o2cb_err.h>
+
+#include <o2cb/ocfs2_heartbeat.h>
+#include <o2cb/ocfs2_nodemanager.h>
+#include <o2cb/ocfs2_tcp.h>
+#endif
+
+#endif /* _O2CB_H */
Added: trunk/libo2cb/include/o2cb_abi.h
===================================================================
--- trunk/libo2cb/include/o2cb_abi.h 2004-12-14 23:50:34 UTC (rev 489)
+++ trunk/libo2cb/include/o2cb_abi.h 2004-12-14 23:59:14 UTC (rev 490)
@@ -0,0 +1,35 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * o2cb_abi.c
+ *
+ * Kernel<->User ABI for modifying cluster configuration.
+ *
+ * Copyright (C) 2004 Oracle. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+
+#ifndef _O2CB_ABI_H
+#define _O2CB_ABI_H
+
+/* Hardcoded paths to the cluster virtual files */
+#define O2CB_CLUSTER_FILE "/proc/cluster/nm/.cluster"
+#define O2CB_GROUP_FILE "/proc/cluster/nm/.group"
+#define O2CB_NODE_FILE "/proc/cluster/nm/.node"
+
+int o2cb_set_cluster_name(const char *cluster_name);
+
+#endif /* _O2CB_ABI_H */
Modified: trunk/libo2cb/include/ocfs2_heartbeat.h
===================================================================
--- trunk/libo2cb/include/ocfs2_heartbeat.h 2004-12-14 23:50:34 UTC (rev 489)
+++ trunk/libo2cb/include/ocfs2_heartbeat.h 2004-12-14 23:59:14 UTC (rev 490)
@@ -46,14 +46,14 @@
typedef struct _hb_op
{
- u16 magic;
- u16 opcode;
+ __u16 magic;
+ __u16 opcode;
unsigned int fd;
char disk_uuid[CLUSTER_DISK_UUID_LEN+1];
- u16 group_num;
- u32 bits;
- u32 blocks;
- u64 start;
+ __u16 group_num;
+ __u32 bits;
+ __u32 blocks;
+ __u64 start;
} hb_op;
enum {
@@ -79,7 +79,7 @@
typedef struct _hb_disk_heartbeat_block
{
- u64 time;
+ __u64 time;
} hb_disk_heartbeat_block;
Modified: trunk/libo2cb/include/ocfs2_nodemanager.h
===================================================================
--- trunk/libo2cb/include/ocfs2_nodemanager.h 2004-12-14 23:50:34 UTC (rev 489)
+++ trunk/libo2cb/include/ocfs2_nodemanager.h 2004-12-14 23:59:14 UTC (rev 490)
@@ -64,17 +64,17 @@
typedef struct _nm_network_iface
{
- u16 ip_port; /* for simplicity, just define exactly one port for this if */
- u16 ip_version;
+ __u16 ip_port; /* for simplicity, just define exactly one port for this if */
+ __u16 ip_version;
union {
- u32 ip_addr4; /* IPv4 address in NBO */
- u32 ip_addr6[4]; /* IPv6 address in NBO */
+ __u32 ip_addr4; /* IPv4 address in NBO */
+ __u32 ip_addr6[4]; /* IPv6 address in NBO */
} addr_u;
} nm_network_iface;
typedef struct _nm_node_info
{
- u16 node_num;
+ __u16 node_num;
char node_name[NM_MAX_NAME_LEN+1];
nm_network_iface ifaces[NM_MAX_IFACES];
} nm_node_info;
@@ -97,19 +97,19 @@
typedef struct _nm_group_change
{
- u16 group_num;
- u16 node_num;
- u16 slot_num;
+ __u16 group_num;
+ __u16 node_num;
+ __u16 slot_num;
char disk_uuid[CLUSTER_DISK_UUID_LEN+1];
char name[NM_MAX_NAME_LEN+1];
} nm_group_change;
typedef struct _nm_op
{
- u16 magic;
- u16 opcode;
+ __u16 magic;
+ __u16 opcode;
union {
- u16 index;
+ __u16 index;
char name[NM_MAX_NAME_LEN+1];
nm_node_info node;
nm_group_change gc;
Modified: trunk/libo2cb/include/ocfs2_tcp.h
===================================================================
--- trunk/libo2cb/include/ocfs2_tcp.h 2004-12-14 23:50:34 UTC (rev 489)
+++ trunk/libo2cb/include/ocfs2_tcp.h 2004-12-14 23:59:14 UTC (rev 490)
@@ -52,10 +52,10 @@
#define GSD_ACTION_ADD_GROUP_NODE (0x02)
typedef struct _gsd_message
{
- u16 from;
- u8 action;
- u8 namelen;
- u8 name[NM_MAX_NAME_LEN];
+ __u16 from;
+ __u8 action;
+ __u8 namelen;
+ __u8 name[NM_MAX_NAME_LEN];
} gsd_message;
#endif /* DLMNET_H */
Added: trunk/libo2cb/o2cb_abi.c
===================================================================
--- trunk/libo2cb/o2cb_abi.c 2004-12-14 23:50:34 UTC (rev 489)
+++ trunk/libo2cb/o2cb_abi.c 2004-12-14 23:59:14 UTC (rev 490)
@@ -0,0 +1,95 @@
+/* -*- mode: c; c-basic-offset: 8; -*-
+ * vim: noexpandtab sw=8 ts=8 sts=0:
+ *
+ * o2cb_abi.c
+ *
+ * Kernel<->User ABI for modifying cluster configuration.
+ *
+ * Copyright (C) 2004 Oracle. All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public
+ * License, version 2, as published by the Free Software Foundation.
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 021110-1307, USA.
+ */
+
+#define _XOPEN_SOURCE 600 /* Triggers XOPEN2K in features.h */
+#define _LARGEFILE64_SOURCE
+
+#include <inttypes.h>
+#include <string.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <linux/types.h>
+
+#include "o2cb.h"
+
+#include "o2cb_abi.h"
+
+int o2cb_set_cluster_name(const char *cluster_name)
+{
+ int fd, rc, page_size = getpagesize();
+ char *buf;
+ nm_op *op;
+
+ if (strlen(cluster_name) > NM_MAX_NAME_LEN)
+ return O2CB_ET_INVALID_CLUSTER_NAME;
+
+ buf = malloc(sizeof(char*) * page_size);
+ if (!buf)
+ return -errno;
+
+ op = (nm_op *)buf;
+ op->magic = NM_OP_MAGIC;
+ op->opcode = NM_OP_NAME_CLUSTER;
+ strcpy(op->arg_u.name, cluster_name);
+
+ fd = open(O2CB_CLUSTER_FILE, O_RDWR);
+ if (fd < 0) {
+ rc = -errno;
+ goto out;
+ }
+
+ rc = write(fd, op, sizeof(nm_op));
+ if (rc < 0) {
+ rc = -errno;
+ goto out_close;
+ } else if (rc < sizeof(nm_op)) {
+ /* FIXME: What to do here? */
+ }
+
+ memset(buf, 0, page_size);
+ rc = read(fd, buf, page_size);
+ if (rc < 0) {
+ rc = -errno;
+ goto out_close;
+ } else if (!rc) {
+ /* FIXME: What to do here? */
+ } else {
+ if (buf[0] == '\0')
+ rc = 0;
+ /* FIXME: genericize, make better, etc */
+ }
+
+out_close:
+ close(fd);
+out:
+ free(buf);
+
+ return rc;
+} /* o2cb_set_cluster_name() */
+
Added: trunk/libo2cb/o2cb_err.et.in
===================================================================
--- trunk/libo2cb/o2cb_err.et.in 2004-12-14 23:50:34 UTC (rev 489)
+++ trunk/libo2cb/o2cb_err.et.in 2004-12-14 23:59:14 UTC (rev 490)
@@ -0,0 +1,30 @@
+#
+# o2cb_err.et.in
+#
+# Error codes for the O2CB library.
+#
+# Copyright (C) 2004 Oracle. All rights reserved.
+#
+# This program is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public
+# License, version 2, as published by the Free Software Foundation.
+#
+# 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, write to the
+# Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+# Boston, MA 021110-1307, USA.
+#
+ error_table o2cb
+
+ec O2CB_ET_BASE,
+ "O2CB Library version @VERSION@"
+
+ec O2CB_ET_INVALID_CLUSTER_NAME,
+ "Invalid name for a cluster"
+
+ end
Modified: trunk/mount.ocfs2/Makefile
===================================================================
--- trunk/mount.ocfs2/Makefile 2004-12-14 23:50:34 UTC (rev 489)
+++ trunk/mount.ocfs2/Makefile 2004-12-14 23:59:14 UTC (rev 490)
@@ -5,7 +5,7 @@
SBIN_PROGRAMS = mount.ocfs2
INCLUDES = -Iinclude -I$(TOPDIR)/libocfs2/include \
- -I$(TOPDIR)/libocfs2cluster/include
+ -I$(TOPDIR)/libo2cb/include
LIBOCFS2_LIBS = -L$(TOPDIR)/libocfs2 -locfs2
LIBOCFS2_DEPS = $(TOPDIR)/libocfs2/libocfs2.a
More information about the Ocfs2-tools-commits
mailing list