aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJose Bollo <jose.bollo@iot.bzh>2019-02-25 14:45:57 +0100
committerJosé Bollo <jose.bollo@iot.bzh>2019-03-22 12:21:54 +0100
commitcaea0053d2abc141ab585324fb51f8c536db249b (patch)
tree06243bc9d7505db05e70a16065eb8c23497b50fc
parent64ca02ceed8acd4b55e423de6b586a143f5a3c64 (diff)
globmatch: Add globmatch to wrap fnmatch
Change-Id: I1effa961a169cce444ea246f5d7f8839b4937403 Signed-off-by: Jose Bollo <jose.bollo@iot.bzh>
-rw-r--r--CMakeLists.txt1
-rw-r--r--src/CMakeLists.txt2
-rw-r--r--src/afb-api-v3.c4
-rw-r--r--src/afb-args.c1
-rw-r--r--src/afb-export.c1
-rw-r--r--src/afb-hook.c3
-rw-r--r--src/globmatch.c111
-rw-r--r--src/globmatch.h42
-rw-r--r--src/globset.c55
9 files changed, 163 insertions, 57 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 853f5fee..7a7ab429 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -59,6 +59,7 @@ option(WITH_LEGACY_BINDING_V2 "Includes the legacy Binding API version 2" ON
option(WITH_LEGACY_BINDING_VDYN "Includes the legacy Binding API version dynamic" OFF)
option(WITH_DYNAMIC_BINDING "Allow to load dynamic bindings (shared libraries)" ON)
option(WITH_LIBMICROHTTPD "Activates HTTP server through LIBMICROHTTPD" ON)
+option(WITH_FNMATCH "Use fnmatch where possible" ON)
############################################################################
# legacy options
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index e3ee7533..8d898328 100644
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -43,6 +43,7 @@ add_definitions(
-DWITH_FDEV_EPOLL=$<NOT:$<BOOL:${WITH_SYSTEMD}>>
-DWITH_LIBMICROHTTPD=$<BOOL:${WITH_LIBMICROHTTPD}>
-DWITH_MONITORING=$<BOOL:${WITH_MONITORING}>
+ -DWITH_FNMATCH=$<BOOL:${WITH_FNMATCH}>
)
if (WITH_SUPERVISOR)
@@ -109,6 +110,7 @@ SET(AFB_LIB_SOURCES
fdev.c
fdev-epoll.c
fdev-systemd.c
+ globmatch.c
globset.c
jobs.c
locale-root.c
diff --git a/src/afb-api-v3.c b/src/afb-api-v3.c
index 7b889ee8..caaaff4c 100644
--- a/src/afb-api-v3.c
+++ b/src/afb-api-v3.c
@@ -21,7 +21,6 @@
#include <string.h>
#include <assert.h>
#include <errno.h>
-#include <fnmatch.h>
#include <json-c/json.h>
@@ -34,8 +33,9 @@
#include "afb-auth.h"
#include "afb-export.h"
#include "afb-xreq.h"
-#include "verbose.h"
+#include "globmatch.h"
#include "sig-monitor.h"
+#include "verbose.h"
/*
* Description of a binding
diff --git a/src/afb-args.c b/src/afb-args.c
index b7ef1f59..edc0a32f 100644
--- a/src/afb-args.c
+++ b/src/afb-args.c
@@ -574,6 +574,7 @@ static int config_has(struct json_object *config, int optid)
return json_object_object_get_ex(config, name_of_optid(optid), NULL);
}
+__attribute__((unused))
static int config_has_bool(struct json_object *config, int optid)
{
struct json_object *x;
diff --git a/src/afb-export.c b/src/afb-export.c
index 202a73f6..eff17316 100644
--- a/src/afb-export.c
+++ b/src/afb-export.c
@@ -20,7 +20,6 @@
#include <stdio.h>
#include <string.h>
#include <errno.h>
-#include <fnmatch.h>
#include <ctype.h>
#include <json-c/json.h>
diff --git a/src/afb-hook.c b/src/afb-hook.c
index f8b593df..075f6a06 100644
--- a/src/afb-hook.c
+++ b/src/afb-hook.c
@@ -44,9 +44,10 @@
#include "afb-evt.h"
#include "afb-api.h"
#include "afb-msg-json.h"
+
+#include "globmatch.h"
#include "verbose.h"
-#include <fnmatch.h>
#define MATCH(pattern,string) (\
pattern \
? !fnmatch((pattern),(string),FNM_CASEFOLD|FNM_EXTMATCH|FNM_PERIOD) \
diff --git a/src/globmatch.c b/src/globmatch.c
new file mode 100644
index 00000000..4cb1f001
--- /dev/null
+++ b/src/globmatch.c
@@ -0,0 +1,111 @@
+/*
+ * Copyright (C) 2018, 2019 "IoT.bzh"
+ * Author: José Bollo <jose.bollo@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#define _GNU_SOURCE
+
+#include <ctype.h>
+
+#include "globmatch.h"
+
+/**
+ * Matches whether the string 'str' matches the pattern 'pat'
+ * and returns its matching score.
+ *
+ * @param pat the glob pattern
+ * @param str the string to match
+ * @return 0 if no match or number representing the matching score
+ */
+static unsigned match(const char *pat, const char *str, int flags)
+{
+ unsigned r, rs, rr;
+ char c, x;
+ int eq;
+
+ /* scan the prefix without glob */
+ r = 1;
+ while ((c = *pat++) != GLOB) {
+ x = *str++;
+ eq = (flags & FNM_CASEFOLD) ? (tolower(c) == tolower(x)) : (c == x);
+ if (!eq)
+ return 0; /* no match */
+ if (!c)
+ return r; /* match up to end */
+ r++;
+ }
+
+ /* glob found */
+ c = *pat++;
+ if (!c) {
+ /* not followed by pattern */
+ if (flags & FNM_PATHNAME) {
+ while(*str)
+ if (*str++ == '/')
+ return 0;
+ }
+ return r;
+ }
+
+ /* evaluate the best score for following pattern */
+ rs = 0;
+ while (*str) {
+ x = *str++;
+ eq = (flags & FNM_CASEFOLD) ? (tolower(c) == tolower(x)) : (c == x);
+ if (eq) {
+ /* first char matches, check remaining string */
+ rr = match(pat, str, flags);
+ if (rr > rs)
+ rs = rr;
+ } else if ((flags & FNM_PATHNAME) && x == '/')
+ return 0;
+ }
+
+ /* best score or not match if rs == 0 */
+ return rs ? rs + r : 0;
+}
+
+/**
+ * Matches whether the string 'str' matches the pattern 'pat'
+ * and returns its matching score.
+ *
+ * @param pat the glob pattern
+ * @param str the string to match
+ * @return 0 if no match or number representing the matching score
+ */
+unsigned globmatch(const char *pat, const char *str)
+{
+ return match(pat, str, 0);
+}
+
+/**
+ * Matches whether the string 'str' matches the pattern 'pat'
+ * and returns its matching score.
+ *
+ * @param pat the glob pattern
+ * @param str the string to match
+ * @return 0 if no match or number representing the matching score
+ */
+unsigned globmatchi(const char *pat, const char *str)
+{
+ return match(pat, str, FNM_CASEFOLD);
+}
+
+#if !WITH_FNMATCH
+int fnmatch(const char *pattern, const char *string, int flags)
+{
+ return !match(pattern, string, flags);
+}
+#endif
diff --git a/src/globmatch.h b/src/globmatch.h
new file mode 100644
index 00000000..2f05c169
--- /dev/null
+++ b/src/globmatch.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (C) 2018, 2019 "IoT.bzh"
+ * Author: José Bollo <jose.bollo@iot.bzh>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#pragma once
+
+#define GLOB '*'
+
+extern unsigned globmatch(const char *pat, const char *str);
+extern unsigned globmatchi(const char *pat, const char *str);
+
+#if WITH_FNMATCH
+
+#include <fnmatch.h>
+
+#else
+
+#define FNM_PATHNAME (1 << 0) /* No wildcard can ever match `/'. */
+#define FNM_NOESCAPE (1 << 1) /* Backslashes don't quote special chars. */
+#define FNM_PERIOD (1 << 2) /* Leading `.' is matched only explicitly. */
+#define FNM_FILE_NAME FNM_PATHNAME /* Preferred GNU name. */
+#define FNM_LEADING_DIR (1 << 3) /* Ignore `/...' after a match. */
+#define FNM_CASEFOLD (1 << 4) /* Compare without regard to case. */
+#define FNM_EXTMATCH (1 << 5) /* Use ksh-like extended matching. */
+#define FNM_NOMATCH 1
+
+extern int fnmatch(const char *pattern, const char *string, int flags);
+
+#endif
diff --git a/src/globset.c b/src/globset.c
index 2bad449f..0ea448be 100644
--- a/src/globset.c
+++ b/src/globset.c
@@ -22,8 +22,7 @@
#include <errno.h>
#include "globset.h"
-
-#define GLOB '*'
+#include "globmatch.h"
/*************************************************************************
* internal types
@@ -63,49 +62,6 @@ struct globset
};
/**
- * Matches whether the string 'str' matches the pattern 'pat'
- * and returns its matching score.
- *
- * @param pat the glob pattern
- * @param str the string to match
- * @return 0 if no match or number representing the matching score
- */
-static unsigned match(const char *pat, const char *str)
-{
- unsigned r, rs, rr;
- char c;
-
- /* scan the prefix without glob */
- r = 1;
- while ((c = *pat++) != GLOB) {
- if (c != *str++)
- return 0; /* no match */
- if (!c)
- return r; /* match up to end */
- r++;
- }
-
- /* glob found */
- c = *pat++;
- if (!c)
- return r; /* not followed by pattern */
-
- /* evaluate the best score for following pattern */
- rs = 0;
- while (*str) {
- if (*str++ == c) {
- /* first char matches, check remaining string */
- rr = match(pat, str);
- if (rr > rs)
- rs = rr;
- }
- }
-
- /* best score or not match if rs == 0 */
- return rs ? rs + r : 0;
-}
-
-/**
* Normalize the string 'from' to the string 'to' and computes the hash code.
* The normalization translates upper characters to lower characters.
* The returned hash code is greater than zero for exact patterns or zero
@@ -235,13 +191,6 @@ static struct pathndl *search(
return ph;
}
-
-
-
-
-
-
-
/**
* Allocates a new set of handlers
*
@@ -436,7 +385,7 @@ const struct globset_handler *globset_match(
s = 0;
iph = set->globs;
while(iph) {
- g = match(iph->handler.pattern, txt);
+ g = globmatch(iph->handler.pattern, txt);
if (g > s) {
s = g;
ph = iph;