summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorNiels de Vos <ndevos@redhat.com>2015-01-01 13:15:45 +0100
committerVijay Bellur <vbellur@redhat.com>2015-03-03 12:31:38 -0800
commit95d5e60afb29aedc29909340e7564d54a6a247c2 (patch)
tree9d0c2b2963e0b74add7109b5952c1252d868c3cf
parent2acfbcf34ed77985905b2d122adbfd541eb01db1 (diff)
core: add generic parser utility
This generic parser will get used for parsing the netgroups and exports files for the Gluster/NFS server. The parsing of netgroups shows how the parser can be used (see Change-Id Ie04800d4). BUG: 1143880 Change-Id: Id4cf2b0189ef5799c06868d211d3fcd9c8608c08 Original-author: Shreyas Siravara <shreyas.siravara@gmail.com> CC: Richard Wareing <rwareing@fb.com> CC: Jiffin Tony Thottan <jthottan@redhat.com> Signed-off-by: Niels de Vos <ndevos@redhat.com> Reviewed-on: http://review.gluster.org/9359 Tested-by: Gluster Build System <jenkins@build.gluster.com> Reviewed-by: Vijay Bellur <vbellur@redhat.com>
-rw-r--r--libglusterfs/src/Makefile.am4
-rw-r--r--libglusterfs/src/common-utils.h15
-rw-r--r--libglusterfs/src/parse-utils.c178
-rw-r--r--libglusterfs/src/parse-utils.h50
4 files changed, 245 insertions, 2 deletions
diff --git a/libglusterfs/src/Makefile.am b/libglusterfs/src/Makefile.am
index b403f2c3bf7..181babe85b0 100644
--- a/libglusterfs/src/Makefile.am
+++ b/libglusterfs/src/Makefile.am
@@ -28,7 +28,7 @@ libglusterfs_la_SOURCES = dict.c xlator.c logging.c \
event-history.c gidcache.c ctx.c client_t.c event-poll.c event-epoll.c \
syncop-utils.c \
$(CONTRIBDIR)/libgen/basename_r.c $(CONTRIBDIR)/libgen/dirname_r.c \
- $(CONTRIBDIR)/stdlib/gf_mkostemp.c strfd.c \
+ $(CONTRIBDIR)/stdlib/gf_mkostemp.c strfd.c parse-utils.c \
$(CONTRIBDIR)/mount/mntent.c $(CONTRIBDIR)/libexecinfo/execinfo.c
nodist_libglusterfs_la_SOURCES = y.tab.c graph.lex.c
@@ -45,7 +45,7 @@ noinst_HEADERS = common-utils.h defaults.h dict.h glusterfs.h hashfn.h timespec.
$(CONTRIB_BUILDDIR)/uuid/uuid_types.h syncop.h graph-utils.h trie.h \
run.h options.h lkowner.h fd-lk.h circ-buff.h event-history.h \
gidcache.h client_t.h glusterfs-acl.h glfs-message-id.h \
- template-component-messages.h strfd.h syncop-utils.h \
+ template-component-messages.h strfd.h syncop-utils.h parse-utils.h \
$(CONTRIBDIR)/mount/mntent_compat.h lvm-defaults.h \
$(CONTRIBDIR)/libexecinfo/execinfo_compat.h
diff --git a/libglusterfs/src/common-utils.h b/libglusterfs/src/common-utils.h
index 6e1669912cd..71ff9eab5de 100644
--- a/libglusterfs/src/common-utils.h
+++ b/libglusterfs/src/common-utils.h
@@ -166,6 +166,21 @@ int gf_set_log_ident (cmd_args_t *cmd_args);
} \
}while (0)
+#define GF_CHECK_ALLOC(arg, retval, label) do { \
+ if (!(arg)) { \
+ retval = -ENOMEM; \
+ goto label; \
+ } \
+ } while (0) \
+
+#define GF_CHECK_ALLOC_AND_LOG(name, item, retval, msg, errlabel) do { \
+ if (!(item)) { \
+ (retval) = -ENOMEM; \
+ gf_log (name, GF_LOG_CRITICAL, (msg)); \
+ goto errlabel; \
+ } \
+ } while (0)
+
#define GF_ASSERT_AND_GOTO_WITH_ERROR(name, arg, label, errno, error) do { \
if (!arg) { \
GF_ASSERT (0); \
diff --git a/libglusterfs/src/parse-utils.c b/libglusterfs/src/parse-utils.c
new file mode 100644
index 00000000000..3934586aa32
--- /dev/null
+++ b/libglusterfs/src/parse-utils.c
@@ -0,0 +1,178 @@
+/*
+ Copyright 2014-present Facebook. All Rights Reserved
+
+ This file is part of GlusterFS.
+
+ Author :
+ Shreyas Siravara <shreyas.siravara@gmail.com>
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+#include <regex.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include "parse-utils.h"
+#include "mem-pool.h"
+#include "common-utils.h"
+
+/**
+ * parser_init: Initialize a parser with the a string to parse and
+ * the regex we want to use to parse it.
+ *
+ * @complete_str: the string to parse
+ * @regex : the regex to use
+ *
+ * Notes : It is up to the caller to call the parser_deinit () function
+ * to free the allocated parser.
+ *
+ * @return : success: parser ptr (on successful compilation and allocation)
+ * : failure: NULL (on failure to compile regex or allocate memory)
+ */
+struct parser *
+parser_init (const char *regex)
+{
+ int rc = 0;
+ struct parser *parser = NULL;
+
+ parser = MALLOC (sizeof(*parser));
+ if (!parser)
+ goto out;
+
+ parser->regex = gf_strdup (regex);
+ if (!parser->regex) {
+ gf_log (GF_PARSE, GF_LOG_INFO,
+ "Failed to duplicate regex string!");
+ FREE (parser);
+ parser = NULL;
+ goto out;
+ }
+
+ rc = regcomp (&parser->preg, parser->regex, REG_EXTENDED);
+ if (rc != 0) {
+ gf_log (GF_PARSE, GF_LOG_INFO,
+ "Failed to compile regex pattern.");
+ parser_deinit (parser);
+ parser = NULL;
+ goto out;
+ }
+ parser->complete_str = NULL;
+out:
+ return parser;
+}
+
+/**
+ * parser_set_string -- Set the string in the parser that we want to parse.
+ * Subsequent calls to get_next_match () will use this
+ * string along with the regex that the parser was
+ * initialized with.
+ *
+ * @parser : The parser to use
+ * @complete_str: The string to set in the parser (what we are going parse)
+ *
+ * @return: success: 0
+ * failure: -EINVAL for NULL args, -ENOMEM for allocation errors
+ */
+int
+parser_set_string (struct parser *parser, const char *complete_str)
+{
+ int ret = -EINVAL;
+
+ GF_VALIDATE_OR_GOTO (GF_PARSE, parser, out);
+ GF_VALIDATE_OR_GOTO (GF_PARSE, complete_str, out);
+
+ parser->complete_str = gf_strdup (complete_str);
+ GF_CHECK_ALLOC_AND_LOG (GF_PARSE, parser, ret,
+ "Failed to duplicate string!", out);
+
+ /* Point the temp internal string to what we just dup'ed */
+ parser->_rstr = (char *)parser->complete_str;
+ ret = 0;
+out:
+ return ret;
+}
+
+/**
+ * parser_unset_string -- Free the string that was set to be parsed.
+ * This function needs to be called after
+ * parser_set_string and parser_get_next_match
+ * in order to free memory used by the string.
+ *
+ * @parser : The parser to free memory in
+ * @return : success: 0
+ * : failure: -EINVAL on NULL args
+ */
+int
+parser_unset_string (struct parser *parser)
+{
+ int ret = -EINVAL;
+
+ GF_VALIDATE_OR_GOTO (GF_PARSE, parser, out);
+
+ GF_FREE (parser->complete_str);
+ parser->complete_str = NULL; /* Avoid double frees in parser_deinit */
+ ret = 0;
+out:
+ return ret;
+}
+
+/**
+ * parser_deinit: Free the parser and all the memory allocated by it
+ *
+ * @parser : Parser to free
+ *
+ * @return : nothing
+ */
+void
+parser_deinit (struct parser *ptr)
+{
+ if (!ptr)
+ return;
+
+ regfree (&ptr->preg);
+ FREE (ptr->complete_str);
+ GF_FREE (ptr->regex);
+ FREE (ptr);
+}
+
+/**
+ * parser_get_match: Given the parser that is configured with a compiled regex,
+ * return the next match in the string.
+ *
+ * @parser : Parser to use
+ *
+ * @return : success: Pointer to matched character
+ * : failure: NULL
+ */
+char *
+parser_get_next_match (struct parser *parser)
+{
+ int rc = -EINVAL;
+ size_t copy_len = 0;
+ char *match = NULL;
+
+ GF_VALIDATE_OR_GOTO (GF_PARSE, parser, out);
+
+ rc = regexec (&parser->preg, parser->_rstr, 1, parser->pmatch, 0);
+ if (rc != 0) {
+ gf_log (GF_PARSE, GF_LOG_DEBUG,
+ "Could not match %s with regex %s",
+ parser->_rstr, parser->regex);
+ goto out;
+ }
+
+ copy_len = parser->pmatch[0].rm_eo - parser->pmatch[0].rm_so;
+
+ match = gf_strndup (parser->_rstr + parser->pmatch[0].rm_so, copy_len);
+ GF_CHECK_ALLOC_AND_LOG (GF_PARSE, match, rc,
+ "Duplicating match failed!", out);
+
+ parser->_rstr = &parser->_rstr[parser->pmatch[0].rm_eo];
+out:
+ return match;
+}
diff --git a/libglusterfs/src/parse-utils.h b/libglusterfs/src/parse-utils.h
new file mode 100644
index 00000000000..275ccf3153b
--- /dev/null
+++ b/libglusterfs/src/parse-utils.h
@@ -0,0 +1,50 @@
+/*
+ Copyright 2014-present Facebook. All Rights Reserved
+
+ This file is part of GlusterFS.
+
+ Author :
+ Shreyas Siravara <shreyas.siravara@gmail.com>
+
+ This file is licensed to you under your choice of the GNU Lesser
+ General Public License, version 3 or any later version (LGPLv3 or
+ later), or the GNU General Public License, version 2 (GPLv2), in all
+ cases as published by the Free Software Foundation.
+*/
+
+#ifndef _PARSE_UTILS_H
+#define _PARSE_UTILS_H
+
+#include <regex.h>
+
+#define GF_PARSE "parse-utils"
+
+struct parser {
+ regex_t preg; /* Compiled regex */
+ regmatch_t pmatch[1]; /* The match */
+ char *complete_str; /* The string we are parsing */
+ char *regex; /* Regex used to parse the string */
+ char *_rstr; /* Temp string to hold offsets */
+};
+
+/* Initializes some of the parsers variables */
+struct parser *
+parser_init (const char *regex);
+
+/* Sets the string to parse */
+int
+parser_set_string (struct parser *parser, const char *complete_str);
+
+/* Frees memory used by the string after all matches are found */
+int
+parser_unset_string (struct parser *parser);
+
+/* Free memory used by the parser */
+void
+parser_deinit (struct parser *ptr);
+
+/* Get the next matching string */
+char *
+parser_get_next_match (struct parser *parser);
+
+#endif /* _PARSE_UTILS_H */