/* * Copyright (C) 2018, 2019 "IoT.bzh" * Author: José Bollo * * 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 #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