From a262eebe347ffce798ea86684226b4ef2a4c6701 Mon Sep 17 00:00:00 2001 From: Xiang Xiao Date: Sun, 1 Aug 2021 16:54:08 +0800 Subject: [PATCH] libc: Rename match to fnmatch specified here: https://pubs.opengroup.org/onlinepubs/007904875/functions/fnmatch.html Signed-off-by: Xiang Xiao --- fs/procfs/fs_procfs.c | 8 +- include/fnmatch.h | 110 ++++++++++++++++++ libs/libc/libc.csv | 1 + libs/libc/misc/Make.defs | 2 +- libs/libc/misc/lib_fnmatch.c | 210 +++++++++++++++++++++++++++++++++++ net/procfs/net_procfs.c | 7 +- 6 files changed, 330 insertions(+), 8 deletions(-) create mode 100644 include/fnmatch.h create mode 100644 libs/libc/misc/lib_fnmatch.c diff --git a/fs/procfs/fs_procfs.c b/fs/procfs/fs_procfs.c index 3c5dace4fd9..e0a41c7a1d9 100644 --- a/fs/procfs/fs_procfs.c +++ b/fs/procfs/fs_procfs.c @@ -34,6 +34,7 @@ #include #include #include +#include #include #include #include @@ -45,7 +46,6 @@ #include #include #include -#include #include "mount/mount.h" @@ -351,7 +351,7 @@ static int procfs_open(FAR struct file *filep, FAR const char *relpath, { /* Test if the path matches this entry's specification */ - if (match(g_procfs_entries[x].pathpattern, relpath)) + if (fnmatch(g_procfs_entries[x].pathpattern, relpath, 0) == 0) { /* Match found! Stat using this procfs entry */ @@ -594,7 +594,7 @@ static int procfs_opendir(FAR struct inode *mountpt, FAR const char *relpath, { /* Test if the path matches this entry's specification */ - if (match(g_procfs_entries[x].pathpattern, relpath)) + if (fnmatch(g_procfs_entries[x].pathpattern, relpath, 0) == 0) { /* Match found! Call the handler's opendir routine. If * successful, this opendir routine will create an entry @@ -1041,7 +1041,7 @@ static int procfs_stat(struct inode *mountpt, const char *relpath, { /* Test if the path matches this entry's specification */ - if (match(g_procfs_entries[x].pathpattern, relpath)) + if (fnmatch(g_procfs_entries[x].pathpattern, relpath, 0) == 0) { /* Match found! Stat using this procfs entry */ diff --git a/include/fnmatch.h b/include/fnmatch.h new file mode 100644 index 00000000000..bac89d6623e --- /dev/null +++ b/include/fnmatch.h @@ -0,0 +1,110 @@ +/**************************************************************************** + * include/fnmatch.h + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. The + * ASF licenses this file to you 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. + * + ****************************************************************************/ + +#ifndef __INCLUDE_FNMATCH_H +#define __INCLUDE_FNMATCH_H + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Pre-processor Definitions + ****************************************************************************/ + +#define FNM_PATHNAME 0x01 +#define FNM_PERIOD 0x02 +#define FNM_NOESCAPE 0x04 + +#define FNM_NOMATCH 1 +#define FNM_NOSYS -1 + +/**************************************************************************** + * Public Function Prototypes + ****************************************************************************/ + +#ifdef __cplusplus +#define EXTERN extern "C" +extern "C" +{ +#else +#define EXTERN extern +#endif + +/**************************************************************************** + * Name: fnmatch + * + * Description: + * The fnmatch() function shall match patterns as described in the Shell + * and Utilities volume of IEEE Std 1003.1-2001, Section 2.13.1, Patterns + * Matching a Single Character, and Section 2.13.2, Patterns Matching + * Multiple Characters. It checks the string specified by the string + * argument to see if it matches the pattern specified by the pattern + * argument. + * + * The flags argument shall modify the interpretation of pattern and + * string. It is the bitwise-inclusive OR of zero or more of the flags + * defined in . If the FNM_PATHNAME flag is set in flags, + * then a slash character ( '/' ) in string shall be explicitly matched + * by a slash in pattern; it shall not be matched by either the asterisk + * or question-mark special characters, nor by a bracket expression. If + * the FNM_PATHNAME flag is not set, the slash character shall be treated + * as an ordinary character. + * + * If FNM_NOESCAPE is not set in flags, a backslash character ( '\' ) in + * pattern followed by any other character shall match that second + * character in string. In particular, "\\" shall match a backslash in + * string. If FNM_NOESCAPE is set, a backslash character shall be treated + * as an ordinary character. + * + * If FNM_PERIOD is set in flags, then a leading period ( '.' ) in string + * shall match a period in pattern; as described by rule 2 in the Shell and + * Utilities volume of IEEE Std 1003.1-2001, Section 2.13.3, Patterns Used + * for Filename Expansion where the location of "leading" is indicated by + * the value of FNM_PATHNAME: + * + * If FNM_PATHNAME is set, a period is "leading" if it is the first + * character in string or if it immediately follows a slash. + * + * If FNM_PATHNAME is not set, a period is "leading" only if it is the + * first character of string. + * + * If FNM_PERIOD is not set, then no special restrictions are placed on + * matching a period. + * + * Returned Value: + * If string matches the pattern specified by pattern, then fnmatch() + * shall return 0. If there is no match, fnmatch() shall return + * FNM_NOMATCH, which is defined in . If an error occurs, + * fnmatch() shall return another non-zero value. + * + ****************************************************************************/ + +int fnmatch(FAR const char *pattern, const char *string, int flags); + +#undef EXTERN +#ifdef __cplusplus +} +#endif + +#endif /* __INCLUDE_FNMATCH_H */ diff --git a/libs/libc/libc.csv b/libs/libc/libc.csv index f0bd9c8d045..b505164c42d 100644 --- a/libs/libc/libc.csv +++ b/libs/libc/libc.csv @@ -42,6 +42,7 @@ "fgetpos","stdio.h","defined(CONFIG_FILE_STREAM)","int","FAR FILE *","FAR fpos_t *" "fgets","stdio.h","defined(CONFIG_FILE_STREAM)","FAR char *","FAR char *","int","FAR FILE *" "fileno","stdio.h","","int","FAR FILE *" +"fnmatch","fnmatch.h","","int","FAR const char *","FAR const char *","int" "fopen","stdio.h","defined(CONFIG_FILE_STREAM)","FAR FILE *","FAR const char *","FAR const char *" "fprintf","stdio.h","defined(CONFIG_FILE_STREAM)","int","FAR FILE *","FAR const IPTR char *","..." "fputc","stdio.h","defined(CONFIG_FILE_STREAM)","int","int","FAR FILE *" diff --git a/libs/libc/misc/Make.defs b/libs/libc/misc/Make.defs index 2168826a125..af9478456d5 100644 --- a/libs/libc/misc/Make.defs +++ b/libs/libc/misc/Make.defs @@ -44,7 +44,7 @@ endif # Add the miscellaneous C files to the build -CSRCS += lib_dumpbuffer.c lib_dumpvbuffer.c lib_match.c lib_debug.c +CSRCS += lib_dumpbuffer.c lib_dumpvbuffer.c lib_fnmatch.c lib_match.c lib_debug.c CSRCS += lib_crc64.c lib_crc32.c lib_crc16.c lib_crc8.c lib_crc8ccitt.c CSRCS += lib_crc8table.c diff --git a/libs/libc/misc/lib_fnmatch.c b/libs/libc/misc/lib_fnmatch.c new file mode 100644 index 00000000000..7e2e8947fec --- /dev/null +++ b/libs/libc/misc/lib_fnmatch.c @@ -0,0 +1,210 @@ +/**************************************************************************** + * libs/libc/misc/lib_fnmatch.c + * + * Simple shell-style filename pattern matcher written by Jef Poskanzer + * This pattern matcher only handles '?', '*' and '**', and multiple + * patterns separated by '|'. + * + * Copyright 1995, 2000 by Jef Poskanzer . + * All rights reserved. + * + * With extensions by Ken Pettit. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + ****************************************************************************/ + +/**************************************************************************** + * Included Files + ****************************************************************************/ + +#include +#include + +/**************************************************************************** + * Private Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fnmatch_one + * + * Description: + * Does all of the work for one '|' delimited pattern + * + * Returned Value: + * Returns 0 (match) or 1 (no-match). + * + ****************************************************************************/ + +static int fnmatch_one(FAR const char *pattern, int patlen, + FAR const char *string, int flags) +{ + FAR const char *p; + char first; + int pl; + int i; + + for (p = pattern; p - pattern < patlen; p++, string++) + { + if (*p == '?' && *string != '\0') + { + continue; + } + + /* Match single character from a set: "[a-zA-Z]" for instance */ + + if (*p == '[' && *string != '\0') + { + i = 0; + while (*p != ']' && *p != '\0') + { + p++; + + if (*string == *p) + { + /* Match found. Advance to the ']' */ + + i = 1; + while (*p != ']' && *p != '\0') + { + p++; + } + + break; + } + + /* Prepare to test for range */ + + if (*p != '\0') + { + first = *p++; + if (*p == '-') + { + p++; + if (*string >= first && *string <= *p) + { + /* Match found. Advance to the ']' */ + + i = 1; + while (*p != ']' && *p != '\0') + { + p++; + } + + break; + } + } + } + } + + /* We reuse 'i' above to indicate match found */ + + if (i) + { + continue; + } + + return FNM_NOMATCH; + } + + if (*p == '*') + { + p++; + if (*p == '*') + { + /* Double-wildcard matches anything. */ + + p++; + i = strlen(string); + } + else + { + /* Single-wildcard matches anything but slash. */ + + i = strcspn(string, "/"); + } + + pl = patlen - (p - pattern); + for (; i >= 0; i--) + { + if (fnmatch_one(p, pl, &string[i], flags) == 0) + { + return 0; + } + } + + return FNM_NOMATCH; + } + + if (*p != *string) + { + return FNM_NOMATCH; + } + } + + if (*string == '\0') + { + return 0; + } + + return FNM_NOMATCH; +} + +/**************************************************************************** + * Public Functions + ****************************************************************************/ + +/**************************************************************************** + * Name: fnmatch + * + * Description: + * Simple shell-style filename pattern matcher originally written by + * Jef Poskanzer and extended by Ken Pettit. This pattern matcher handles + * '?', '*', '**', sets like [a-zA-z], and multiple patterns separated + * by '|'. + * + * Returned Value: + * Returns 0 (match) or 1 (no-match). + * + ****************************************************************************/ + +int fnmatch(FAR const char *pattern, const char *string, int flags) +{ + FAR const char *or; + + for (; ; ) + { + or = strchr(pattern, '|'); + if (or == NULL) + { + return fnmatch_one(pattern, strlen(pattern), string, flags); + } + + if (fnmatch_one(pattern, or - pattern, string, flags) == 0) + { + return 0; + } + + pattern = or + 1; + } +} diff --git a/net/procfs/net_procfs.c b/net/procfs/net_procfs.c index 421b41df845..39e68e64a47 100644 --- a/net/procfs/net_procfs.c +++ b/net/procfs/net_procfs.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -40,7 +41,6 @@ #include #include #include -#include #include #include "netdev/netdev.h" @@ -185,7 +185,7 @@ static int netprocfs_open(FAR struct file *filep, FAR const char *relpath, * table support is initialized. */ - if (match("net/route/**", relpath)) + if (fnmatch("net/route/**", relpath, 0) == 0) { /* Use the /net/route directory */ @@ -393,7 +393,8 @@ static int netprocfs_opendir(FAR const char *relpath, */ #ifdef CONFIG_NET_ROUTE - if (match("net/route", relpath) || match("net/route/**", relpath)) + if (fnmatch("net/route", relpath, 0) == 0 || + fnmatch("net/route/**", relpath, 0) == 0) { /* Use the /net/route directory */