diff --git a/dap-sdk/core/include/dap_fnmatch.h b/dap-sdk/core/include/dap_fnmatch.h new file mode 100644 index 0000000000000000000000000000000000000000..9afaba94581823c6ae1c909b7d18cce9a712c2b5 --- /dev/null +++ b/dap-sdk/core/include/dap_fnmatch.h @@ -0,0 +1,62 @@ +/* Copyright (C) 1991-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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.1 of the License, or (at your option) any later version. + + The GNU C 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#ifndef _FNMATCH_H +#define _FNMATCH_H 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/* We #undef these before defining them because some losing systems + (HP-UX A.08.07 for example) define these in <unistd.h>. */ +#undef FNM_PATHNAME +#undef FNM_NOESCAPE +#undef FNM_PERIOD + +/* Bits set in the FLAGS argument to `fnmatch'. */ +#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. */ + +#if !defined _POSIX_C_SOURCE || _POSIX_C_SOURCE < 2 || defined _GNU_SOURCE +# 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. */ +#endif + +/* Value returned by `fnmatch' if STRING does not match PATTERN. */ +#define FNM_NOMATCH 1 + +/* This value is returned if the implementation does not support + `fnmatch'. Since this is not the case here it will never be + returned but the conformance test suites still require the symbol + to be defined. */ +#ifdef _XOPEN_SOURCE +# define FNM_NOSYS (-1) +#endif + +/* Match NAME against the filename pattern PATTERN, + returning zero if it matches, FNM_NOMATCH if not. */ +extern int dap_fnmatch (const char *__pattern, const char *__name, int __flags); + +#ifdef __cplusplus +} +#endif + +#endif /* fnmatch.h */ diff --git a/dap-sdk/core/include/dap_fnmatch_loop.h b/dap-sdk/core/include/dap_fnmatch_loop.h new file mode 100644 index 0000000000000000000000000000000000000000..550b5d80164380aea6aecbb092cd3dcbf60004c1 --- /dev/null +++ b/dap-sdk/core/include/dap_fnmatch_loop.h @@ -0,0 +1,1223 @@ +/* Copyright (C) 1991-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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.1 of the License, or (at your option) any later version. + + The GNU C 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <stdlib.h> +#include <stdint.h> +#include <stddef.h> +#include "dap_fnmatch.h" + +struct STRUCT +{ + const char *pattern; + const char *string; + int no_leading_period; +}; + +#define L_func(CS) CS +/* Global variable. */ +static int posixly_correct; +# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ + +/* Match STRING against the filename pattern PATTERN, returning zero if + it matches, nonzero if not. */ +static int FCT (const char *pattern, const char *string, + const char *string_end, int no_leading_period, int flags, + struct STRUCT *ends, size_t alloca_used); +static int EXT (int opt, const char *pattern, const char *string, + const char *string_end, int no_leading_period, int flags, + size_t alloca_used); +static const char *END (const char *patternp); + +static int +FCT (const char *pattern, const char *string, const char *string_end, + int no_leading_period, int flags, struct STRUCT *ends, size_t alloca_used) +{ + const char *p = pattern, *n = string; + unsigned char c; +#ifdef _LIBC +# if WIDE_CHAR_VERSION + const char *collseq = (const char *) + _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQWC); +# else + const unsigned char *collseq = (const unsigned char *) + _NL_CURRENT(LC_COLLATE, _NL_COLLATE_COLLSEQMB); +# endif +#endif + + while ((c = *p++) != '\0') + { + int new_no_leading_period = 0; + c = FOLD (c); + + switch (c) + { + case '?': + if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') + { + int res = EXT (c, p, n, string_end, no_leading_period, + flags, alloca_used); + if (res != -1) + return res; + } + + if (n == string_end) + return FNM_NOMATCH; + else if (*n == '/' && (flags & FNM_FILE_NAME)) + return FNM_NOMATCH; + else if (*n == '.' && no_leading_period) + return FNM_NOMATCH; + break; + + case '\\': + if (!(flags & FNM_NOESCAPE)) + { + c = *p++; + if (c == '\0') + /* Trailing \ loses. */ + return FNM_NOMATCH; + c = FOLD (c); + } + if (n == string_end || FOLD ((unsigned char) *n) != c) + return FNM_NOMATCH; + break; + + case '*': + if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') + { + int res = EXT (c, p, n, string_end, no_leading_period, + flags, alloca_used); + if (res != -1) + return res; + } + else if (ends != NULL) + { + ends->pattern = p - 1; + ends->string = n; + ends->no_leading_period = no_leading_period; + return 0; + } + + if (n != string_end && *n == '.' && no_leading_period) + return FNM_NOMATCH; + + for (c = *p++; c == '?' || c == '*'; c = *p++) + { + if (*p == '(' && (flags & FNM_EXTMATCH) != 0) + { + const char *endp = END (p); + if (endp != p) + { + /* This is a pattern. Skip over it. */ + p = endp; + continue; + } + } + + if (c == '?') + { + /* A ? needs to match one character. */ + if (n == string_end) + /* There isn't another character; no match. */ + return FNM_NOMATCH; + else if (*n == '/' + && __builtin_expect (flags & FNM_FILE_NAME, 0)) + /* A slash does not match a wildcard under + FNM_FILE_NAME. */ + return FNM_NOMATCH; + else + /* One character of the string is consumed in matching + this ? wildcard, so *??? won't match if there are + less than three characters. */ + ++n; + } + } + + if (c == '\0') + /* The wildcard(s) is/are the last element of the pattern. + If the name is a file name and contains another slash + this means it cannot match, unless the FNM_LEADING_DIR + flag is set. */ + { + int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH; + + if (flags & FNM_FILE_NAME) + { + if (flags & FNM_LEADING_DIR) + result = 0; + else + { + if (MEMCHR (n, '/', string_end - n) == NULL) + result = 0; + } + } + + return result; + } + else + { + const char *endp; + struct STRUCT end; + + end.pattern = NULL; + endp = MEMCHR (n, (flags & FNM_FILE_NAME) ? '/' : '\0', + string_end - n); + if (endp == NULL) + endp = string_end; + + if (c == '[' + || (__builtin_expect (flags & FNM_EXTMATCH, 0) != 0 + && (c == '@' || c == '+' || c == '!') + && *p == '(')) + { + int flags2 = ((flags & FNM_FILE_NAME) + ? flags : (flags & ~FNM_PERIOD)); + + for (--p; n < endp; ++n, no_leading_period = 0) + if (FCT (p, n, string_end, no_leading_period, flags2, + &end, alloca_used) == 0) + goto found; + } + else if (c == '/' && (flags & FNM_FILE_NAME)) + { + while (n < string_end && *n != '/') + ++n; + if (n < string_end && *n == '/' + && (FCT (p, n + 1, string_end, flags & FNM_PERIOD, flags, + NULL, alloca_used) == 0)) + return 0; + } + else + { + int flags2 = ((flags & FNM_FILE_NAME) + ? flags : (flags & ~FNM_PERIOD)); + + if (c == '\\' && !(flags & FNM_NOESCAPE)) + c = *p; + c = FOLD (c); + for (--p; n < endp; ++n, no_leading_period = 0) + if (FOLD ((unsigned char) *n) == c + && (FCT (p, n, string_end, no_leading_period, flags2, + &end, alloca_used) == 0)) + { + found: + if (end.pattern == NULL) + return 0; + break; + } + if (end.pattern != NULL) + { + p = end.pattern; + n = end.string; + no_leading_period = end.no_leading_period; + continue; + } + } + } + + /* If we come here no match is possible with the wildcard. */ + return FNM_NOMATCH; + + case '[': + { + /* Nonzero if the sense of the character class is inverted. */ + const char *p_init = p; + const char *n_init = n; + int not; + char cold; + unsigned char fn; + + if (posixly_correct == 0) + posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; + + if (n == string_end) + return FNM_NOMATCH; + + if (*n == '.' && no_leading_period) + return FNM_NOMATCH; + + if (*n == L_func('/') && (flags & FNM_FILE_NAME)) + /* `/' cannot be matched. */ + return FNM_NOMATCH; + + not = (*p == '!' || (posixly_correct < 0 && *p == '^')); + if (not) + ++p; + + fn = FOLD ((unsigned char) *n); + + c = *p++; + for (;;) + { + if (!(flags & FNM_NOESCAPE) && c == L_func('\\')) + { + if (*p == L_func('\0')) + return FNM_NOMATCH; + c = FOLD ((unsigned char) *p); + ++p; + + goto normal_bracket; + } + else if (c == L_func('[') && *p == L_func(':')) + { + /* Leave room for the null. */ + char str[CHAR_CLASS_MAX_LENGTH + 1]; + size_t c1 = 0; +#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) + wctype_t wt; +#endif + const char *startp = p; + + for (;;) + { + if (c1 == CHAR_CLASS_MAX_LENGTH) + /* The name is too long and therefore the pattern + is ill-formed. */ + return FNM_NOMATCH; + + c = *++p; + if (c == L_func(':') && p[1] == L_func(']')) + { + p += 2; + break; + } + if (c < L_func('a') || c >= L_func('z')) + { + /* This cannot possibly be a character class name. + Match it as a normal range. */ + p = startp; + c = L_func('['); + goto normal_bracket; + } + str[c1++] = c; + } + str[c1] = L_func('\0'); + +#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) + wt = IS_CHAR_CLASS (str); + if (wt == 0) + /* Invalid character class name. */ + return FNM_NOMATCH; + +# if defined _LIBC && ! WIDE_CHAR_VERSION + /* The following code is glibc specific but does + there a good job in speeding up the code since + we can avoid the btowc() call. */ + if (_ISCTYPE ((unsigned char) *n, wt)) + goto matched; +# else + if (ISWCTYPE (BTOWC ((unsigned char) *n), wt)) + goto matched; +# endif +#else + if ((STREQ (str, L_func("alnum")) && ISALNUM ((unsigned char) *n)) + || (STREQ (str, L_func("alpha")) && ISALPHA ((unsigned char) *n)) + || (STREQ (str, L_func("blank")) && ISBLANK ((unsigned char) *n)) + || (STREQ (str, L_func("cntrl")) && ISCNTRL ((unsigned char) *n)) + || (STREQ (str, L_func("digit")) && ISDIGIT ((unsigned char) *n)) + || (STREQ (str, L_func("graph")) && ISGRAPH ((unsigned char) *n)) + || (STREQ (str, L_func("lower")) && ISLOWER ((unsigned char) *n)) + || (STREQ (str, L_func("print")) && ISPRINT ((unsigned char) *n)) + || (STREQ (str, L_func("punct")) && ISPUNCT ((unsigned char) *n)) + || (STREQ (str, L_func("space")) && ISSPACE ((unsigned char) *n)) + || (STREQ (str, L_func("upper")) && ISUPPER ((unsigned char) *n)) + || (STREQ (str, L_func("xdigit")) && ISXDIGIT ((unsigned char) *n))) + goto matched; +#endif + c = *p++; + } +#ifdef _LIBC + else if (c == L_func('[') && *p == L_func('=')) + { + /* It's important that STR be a scalar variable rather + than a one-element array, because GCC (at least 4.9.2 + -O2 on x86-64) can be confused by the array and + diagnose a "used initialized" in a dead branch in the + findidx function. */ + unsigned char str; + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + const char *startp = p; + + c = *++p; + if (c == L_func('\0')) + { + p = startp; + c = L_func('['); + goto normal_bracket; + } + str = c; + + c = *++p; + if (c != L_func('=') || p[1] != L_func(']')) + { + p = startp; + c = L_func('['); + goto normal_bracket; + } + p += 2; + + if (nrules == 0) + { + if ((unsigned char) *n == str) + goto matched; + } + else + { + const int32_t *table; +# if WIDE_CHAR_VERSION + const int32_t *weights; + const wint_t *extra; +# else + const unsigned char *weights; + const unsigned char *extra; +# endif + const int32_t *indirect; + int32_t idx; + const unsigned char *cp = (const unsigned char *) &str; + +# if WIDE_CHAR_VERSION + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEWC); + weights = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTWC); + extra = (const wint_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAWC); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTWC); +# else + table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_TABLEMB); + weights = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_WEIGHTMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_EXTRAMB); + indirect = (const int32_t *) + _NL_CURRENT (LC_COLLATE, _NL_COLLATE_INDIRECTMB); +# endif + + idx = FINDIDX (table, indirect, extra, &cp, 1); + if (idx != 0) + { + /* We found a table entry. Now see whether the + character we are currently at has the same + equivalance class value. */ + int len = weights[idx & 0xffffff]; + int32_t idx2; + const unsigned char *np = (const unsigned char *) n; + + idx2 = FINDIDX (table, indirect, extra, + &np, string_end - n); + if (idx2 != 0 + && (idx >> 24) == (idx2 >> 24) + && len == weights[idx2 & 0xffffff]) + { + int cnt = 0; + + idx &= 0xffffff; + idx2 &= 0xffffff; + + while (cnt < len + && (weights[idx + 1 + cnt] + == weights[idx2 + 1 + cnt])) + ++cnt; + + if (cnt == len) + goto matched; + } + } + } + + c = *p++; + } +#endif + else if (c == L_func('\0')) + { + /* [ unterminated, treat as normal character. */ + p = p_init; + n = n_init; + c = L_func('['); + goto normal_match; + } + else + { + int is_range = 0; + +#ifdef _LIBC + int is_seqval = 0; + + if (c == L_func('[') && *p == L_func('.')) + { + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, _NL_COLLATE_NRULES); + const char *startp = p; + size_t c1 = 0; + + while (1) + { + c = *++p; + if (c == L_func('.') && p[1] == L_func(']')) + { + p += 2; + break; + } + if (c == '\0') + return FNM_NOMATCH; + ++c1; + } + + /* We have to handling the symbols differently in + ranges since then the collation sequence is + important. */ + is_range = *p == L_func('-') && p[1] != L_func('\0'); + + if (nrules == 0) + { + /* There are no names defined in the collation + data. Therefore we only accept the trivial + names consisting of the character itself. */ + if (c1 != 1) + return FNM_NOMATCH; + + if (!is_range && *n == startp[1]) + goto matched; + + cold = startp[1]; + c = *p++; + } + else + { + int32_t table_size; + const int32_t *symb_table; + const unsigned char *extra; + int32_t idx; + int32_t elem; +# if WIDE_CHAR_VERSION + char *wextra; +# endif + + table_size = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_SYMB_HASH_SIZEMB); + symb_table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_TABLEMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + + for (elem = 0; elem < table_size; elem++) + if (symb_table[2 * elem] != 0) + { + idx = symb_table[2 * elem + 1]; + /* Skip the name of collating element. */ + idx += 1 + extra[idx]; +# if WIDE_CHAR_VERSION + /* Skip the byte sequence of the + collating element. */ + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + + wextra = (char *) &extra[idx + 4]; + + if (/* Compare the length of the sequence. */ + c1 == wextra[0] + /* Compare the wide char sequence. */ + && WMEMCMP (startp + 1, &wextra[1], + c1) == 0) + /* Yep, this is the entry. */ + break; +# else + if (/* Compare the length of the sequence. */ + c1 == extra[idx] + /* Compare the byte sequence. */ + && memcmp (startp + 1, + &extra[idx + 1], c1) == 0) + /* Yep, this is the entry. */ + break; +# endif + } + + if (elem < table_size) + { + /* Compare the byte sequence but only if + this is not part of a range. */ + if (! is_range + +# if WIDE_CHAR_VERSION + && WMEMCMP (n, &wextra[1], c1) == 0 +# else + && memcmp (n, &extra[idx + 1], c1) == 0 +# endif + ) + { + n += c1 - 1; + goto matched; + } + + /* Get the collation sequence value. */ + is_seqval = 1; +# if WIDE_CHAR_VERSION + cold = wextra[1 + wextra[idx]]; +# else + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + cold = *((int32_t *) &extra[idx]); +# endif + + c = *p++; + } + else if (c1 == 1) + { + /* No valid character. Match it as a + single byte. */ + if (!is_range && *n == startp[1]) + goto matched; + + cold = startp[1]; + c = *p++; + } + else + return FNM_NOMATCH; + } + } + else +#endif + { + c = FOLD (c); + normal_bracket: + + /* We have to handling the symbols differently in + ranges since then the collation sequence is + important. */ + is_range = (*p == L_func('-') && p[1] != L_func('\0') + && p[1] != L_func(']')); + + if (!is_range && c == fn) + goto matched; + + /* This is needed if we goto normal_bracket; from + outside of is_seqval's scope. */ + //is_seqval = 0; + cold = c; + c = *p++; + } + + if (c == L_func('-') && *p != L_func(']')) + { +#if _LIBC + /* We have to find the collation sequence + value for C. Collation sequence is nothing + we can regularly access. The sequence + value is defined by the order in which the + definitions of the collation values for the + various characters appear in the source + file. A strange concept, nowhere + documented. */ + uint32_t fcollseq; + uint32_t lcollseq; + unsigned char cend = *p++; + +# if WIDE_CHAR_VERSION + /* Search in the `names' array for the characters. */ + fcollseq = __collseq_table_lookup (collseq, fn); + if (fcollseq == ~((uint32_t) 0)) + /* XXX We don't know anything about the character + we are supposed to match. This means we are + failing. */ + goto range_not_matched; + + if (is_seqval) + lcollseq = cold; + else + lcollseq = __collseq_table_lookup (collseq, cold); +# else + fcollseq = collseq[fn]; + lcollseq = is_seqval ? cold : collseq[(unsigned char) cold]; +# endif + + is_seqval = 0; + if (cend == L_func('[') && *p == L_func('.')) + { + uint32_t nrules = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_NRULES); + const char *startp = p; + size_t c1 = 0; + + while (1) + { + c = *++p; + if (c == L_func('.') && p[1] == L_func(']')) + { + p += 2; + break; + } + if (c == '\0') + return FNM_NOMATCH; + ++c1; + } + + if (nrules == 0) + { + /* There are no names defined in the + collation data. Therefore we only + accept the trivial names consisting + of the character itself. */ + if (c1 != 1) + return FNM_NOMATCH; + + cend = startp[1]; + } + else + { + int32_t table_size; + const int32_t *symb_table; + const unsigned char *extra; + int32_t idx; + int32_t elem; +# if WIDE_CHAR_VERSION + char *wextra; +# endif + + table_size = + _NL_CURRENT_WORD (LC_COLLATE, + _NL_COLLATE_SYMB_HASH_SIZEMB); + symb_table = (const int32_t *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_TABLEMB); + extra = (const unsigned char *) + _NL_CURRENT (LC_COLLATE, + _NL_COLLATE_SYMB_EXTRAMB); + + for (elem = 0; elem < table_size; elem++) + if (symb_table[2 * elem] != 0) + { + idx = symb_table[2 * elem + 1]; + /* Skip the name of collating + element. */ + idx += 1 + extra[idx]; +# if WIDE_CHAR_VERSION + /* Skip the byte sequence of the + collating element. */ + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + + wextra = (char *) &extra[idx + 4]; + + if (/* Compare the length of the + sequence. */ + c1 == wextra[0] + /* Compare the wide char sequence. */ + && WMEMCMP (startp + 1, &wextra[1], + c1) == 0) + /* Yep, this is the entry. */ + break; +# else + if (/* Compare the length of the + sequence. */ + c1 == extra[idx] + /* Compare the byte sequence. */ + && memcmp (startp + 1, + &extra[idx + 1], c1) == 0) + /* Yep, this is the entry. */ + break; +# endif + } + + if (elem < table_size) + { + /* Get the collation sequence value. */ + is_seqval = 1; +# if WIDE_CHAR_VERSION + cend = wextra[1 + wextra[idx]]; +# else + idx += 1 + extra[idx]; + /* Adjust for the alignment. */ + idx = (idx + 3) & ~3; + cend = *((int32_t *) &extra[idx]); +# endif + } + else if (c1 == 1) + { + cend = startp[1]; + c = *p++; + } + else + return FNM_NOMATCH; + } + } + else + { + if (!(flags & FNM_NOESCAPE) && cend == L_func('\\')) + cend = *p++; + if (cend == L_func('\0')) + return FNM_NOMATCH; + cend = FOLD (cend); + } + + /* XXX It is not entirely clear to me how to handle + characters which are not mentioned in the + collation specification. */ + if ( +# if WIDE_CHAR_VERSION + lcollseq == 0xffffffff || +# endif + lcollseq <= fcollseq) + { + /* We have to look at the upper bound. */ + uint32_t hcollseq; + + if (is_seqval) + hcollseq = cend; + else + { +# if WIDE_CHAR_VERSION + hcollseq = + __collseq_table_lookup (collseq, cend); + if (hcollseq == ~((uint32_t) 0)) + { + /* Hum, no information about the upper + bound. The matching succeeds if the + lower bound is matched exactly. */ + if (lcollseq != fcollseq) + goto range_not_matched; + + goto matched; + } +# else + hcollseq = collseq[cend]; +# endif + } + + if (lcollseq <= hcollseq && fcollseq <= hcollseq) + goto matched; + } +# if WIDE_CHAR_VERSION + range_not_matched: +# endif +#else + /* We use a boring value comparison of the character + values. This is better than comparing using + `strcoll' since the latter would have surprising + and sometimes fatal consequences. */ + unsigned char cend = *p++; + + if (!(flags & FNM_NOESCAPE) && cend == L_func('\\')) + cend = *p++; + if (cend == L_func('\0')) + return FNM_NOMATCH; + + /* It is a range. */ + if (cold <= fn && fn <= cend) + goto matched; +#endif + + c = *p++; + } + } + + if (c == L_func(']')) + break; + } + + if (!not) + return FNM_NOMATCH; + break; + + matched: + /* Skip the rest of the [...] that already matched. */ + while ((c = *p++) != L_func (']')) + { + if (c == L_func('\0')) + /* [... (unterminated) loses. */ + return FNM_NOMATCH; + + if (!(flags & FNM_NOESCAPE) && c == L_func('\\')) + { + if (*p == L_func('\0')) + return FNM_NOMATCH; + /* XXX 1003.2d11 is unclear if this is right. */ + ++p; + } + else if (c == L_func('[') && *p == L_func(':')) + { + int c1 = 0; + const char *startp = p; + + while (1) + { + c = *++p; + if (++c1 == CHAR_CLASS_MAX_LENGTH) + return FNM_NOMATCH; + + if (*p == L_func(':') && p[1] == L_func(']')) + break; + + if (c < L_func('a') || c >= L_func('z')) + { + p = startp - 2; + break; + } + } + p += 2; + } + else if (c == L_func('[') && *p == L_func('=')) + { + c = *++p; + if (c == L_func('\0')) + return FNM_NOMATCH; + c = *++p; + if (c != L_func('=') || p[1] != L_func(']')) + return FNM_NOMATCH; + p += 2; + } + else if (c == L_func('[') && *p == L_func('.')) + { + while (1) + { + c = *++p; + if (c == L_func('\0')) + return FNM_NOMATCH; + + if (c == L_func('.') && p[1] == L_func(']')) + break; + } + p += 2; + } + } + if (not) + return FNM_NOMATCH; + } + break; + + case L_func('+'): + case L_func('@'): + case L_func('!'): + if (__builtin_expect (flags & FNM_EXTMATCH, 0) && *p == '(') + { + int res = EXT (c, p, n, string_end, no_leading_period, flags, + alloca_used); + if (res != -1) + return res; + } + goto normal_match; + + case L_func('/'): + if (NO_LEADING_PERIOD (flags)) + { + if (n == string_end || c != (unsigned char) *n) + return FNM_NOMATCH; + + new_no_leading_period = 1; + break; + } + /* FALLTHROUGH */ + default: + normal_match: + if (n == string_end || c != FOLD ((unsigned char) *n)) + return FNM_NOMATCH; + } + + no_leading_period = new_no_leading_period; + ++n; + } + + if (n == string_end) + return 0; + + if ((flags & FNM_LEADING_DIR) && n != string_end && *n == L_func('/')) + /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ + return 0; + + return FNM_NOMATCH; +} + + +const char * +END (const char *pattern) +{ + const char *p = pattern; + + while (1) + if (*++p == L_func('\0')) + /* This is an invalid pattern. */ + return pattern; + else if (*p == L_func('[')) + { + /* Handle brackets special. */ + if (posixly_correct == 0) + posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; + + /* Skip the not sign. We have to recognize it because of a possibly + following ']'. */ + if (*++p == L_func('!') || (posixly_correct < 0 && *p == L_func('^'))) + ++p; + /* A leading ']' is recognized as such. */ + if (*p == L_func(']')) + ++p; + /* Skip over all characters of the list. */ + while (*p != L_func(']')) + if (*p++ == L_func('\0')) + /* This is no valid pattern. */ + return pattern; + } + else if ((*p == L_func('?') || *p == L_func('*') || *p == L_func('+') || *p == L_func('@') + || *p == L_func('!')) && p[1] == L_func('(')) + { + p = END (p + 1); + if (*p == L_func('\0')) + /* This is an invalid pattern. */ + return pattern; + } + else if (*p == L_func(')')) + break; + + return p + 1; +} + + +static int +EXT (int opt, const char *pattern, const char *string, const char *string_end, + int no_leading_period, int flags, size_t alloca_used) +{ + const char *startp; + int level; + struct patternlist + { + struct patternlist *next; + char malloced; + char str[0]; + } *list = NULL; + struct patternlist **lastp = &list; + size_t pattern_len = STRLEN (pattern); + int any_malloced = 0; + const char *p; + const char *rs; + int retval = 0; + + /* Parse the pattern. Store the individual parts in the list. */ + level = 0; + for (startp = p = pattern + 1; level >= 0; ++p) + if (*p == L_func('\0')) + { + /* This is an invalid pattern. */ + retval = -1; + goto out; + } + else if (*p == L_func('[')) + { + /* Handle brackets special. */ + if (posixly_correct == 0) + posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; + + /* Skip the not sign. We have to recognize it because of a possibly + following ']'. */ + if (*++p == L_func('!') || (posixly_correct < 0 && *p == L_func('^'))) + ++p; + /* A leading ']' is recognized as such. */ + if (*p == L_func(']')) + ++p; + /* Skip over all characters of the list. */ + while (*p != L_func(']')) + if (*p++ == L_func('\0')) + { + /* This is no valid pattern. */ + retval = -1; + goto out; + } + } + else if ((*p == L_func('?') || *p == L_func('*') || *p == L_func('+') || *p == L_func('@') + || *p == L_func('!')) && p[1] == L_func('(')) + /* Remember the nesting level. */ + ++level; + else if (*p == L_func(')')) + { + if (level-- == 0) + { + /* This means we found the end of the pattern. */ +#define NEW_PATTERN \ + struct patternlist *newp; \ + size_t slen = (opt == '?' || opt == '@' \ + ? pattern_len : (p - startp + 1)); \ + slen = sizeof (struct patternlist) + (slen * sizeof (char)); \ + int malloced = ! __libc_use_alloca (alloca_used + slen); \ + if (__builtin_expect (malloced, 0)) \ + { \ + newp = malloc (slen); \ + if (newp == NULL) \ + { \ + retval = -2; \ + goto out; \ + } \ + any_malloced = 1; \ + } \ + else \ + newp = alloca_account (slen, alloca_used); \ + newp->next = NULL; \ + newp->malloced = malloced; \ + *((char *) MEMPCPY (newp->str, startp, p - startp)) = L_func('\0'); \ + *lastp = newp; \ + lastp = &newp->next + NEW_PATTERN; + } + } + else if (*p == L_func('|')) + { + if (level == 0) + { + NEW_PATTERN; + startp = p + 1; + } + } + assert (list != NULL); + assert (p[-1] == L_func(')')); +#undef NEW_PATTERN + + switch (opt) + { + case '*': + if (FCT (p, string, string_end, no_leading_period, flags, NULL, + alloca_used) == 0) + goto success; + /* FALLTHROUGH */ + + case '+': + do + { + for (rs = string; rs <= string_end; ++rs) + /* First match the prefix with the current pattern with the + current pattern. */ + if (FCT (list->str, string, rs, no_leading_period, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD, + NULL, alloca_used) == 0 + /* This was successful. Now match the rest with the rest + of the pattern. */ + && (FCT (p, rs, string_end, + rs == string + ? no_leading_period + : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0, + flags & FNM_FILE_NAME + ? flags : flags & ~FNM_PERIOD, NULL, alloca_used) == 0 + /* This didn't work. Try the whole pattern. */ + || (rs != string + && FCT (pattern - 1, rs, string_end, + rs == string + ? no_leading_period + : (rs[-1] == '/' && NO_LEADING_PERIOD (flags) + ? 1 : 0), + flags & FNM_FILE_NAME + ? flags : flags & ~FNM_PERIOD, NULL, + alloca_used) == 0))) + /* It worked. Signal success. */ + goto success; + } + while ((list = list->next) != NULL); + + /* None of the patterns lead to a match. */ + retval = FNM_NOMATCH; + break; + + case '?': + if (FCT (p, string, string_end, no_leading_period, flags, NULL, + alloca_used) == 0) + goto success; + /* FALLTHROUGH */ + + case '@': + do { + /* I cannot believe it but `strcat' is actually acceptable + here. Match the entire string with the prefix from the + pattern list and the rest of the pattern following the + pattern list. */ + if(FCT(STRCAT(list->str, p), string, string_end, + no_leading_period, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD, + NULL, alloca_used) == 0) + /* It worked. Signal success. */ + goto success; + } while((list = list->next) != NULL); + + /* None of the patterns lead to a match. */ + retval = FNM_NOMATCH; + break; + + case '!': + for (rs = string; rs <= string_end; ++rs) + { + struct patternlist *runp; + + for (runp = list; runp != NULL; runp = runp->next) + if (FCT (runp->str, string, rs, no_leading_period, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD, + NULL, alloca_used) == 0) + break; + + /* If none of the patterns matched see whether the rest does. */ + if (runp == NULL + && (FCT (p, rs, string_end, + rs == string + ? no_leading_period + : rs[-1] == '/' && NO_LEADING_PERIOD (flags) ? 1 : 0, + flags & FNM_FILE_NAME ? flags : flags & ~FNM_PERIOD, + NULL, alloca_used) == 0)) + /* This is successful. */ + goto success; + } + + /* None of the patterns together with the rest of the pattern + lead to a match. */ + retval = FNM_NOMATCH; + break; + + default: + assert (! "Invalid extended matching operator"); + retval = -1; + break; + } + + success: + out: + if (any_malloced) + while (list != NULL) + { + struct patternlist *old = list; + list = list->next; + if (old->malloced) + free (old); + } + + return retval; +} + + +#undef FOLD +#undef FCT +#undef EXT +#undef END +#undef STRUCT +#undef MEMPCPY +#undef MEMCHR +#undef STRCOLL +#undef STRLEN +#undef STRCAT +#undef L +#undef BTOWC +#undef WIDE_CHAR_VERSION +#undef FINDIDX diff --git a/dap-sdk/core/include/dap_strfuncs.h b/dap-sdk/core/include/dap_strfuncs.h index c581294cb9df00d18df510e4425c3e4f8787414e..79f00942eaeb5050de51017e3d9ab36b2cd165e6 100755 --- a/dap-sdk/core/include/dap_strfuncs.h +++ b/dap-sdk/core/include/dap_strfuncs.h @@ -13,6 +13,7 @@ #include <string.h> #include "dap_math_ops.h" +#include "dap_fnmatch.h" #define dap_return_if_fail(expr) {if(!(expr)) {return;}} #define dap_return_val_if_fail(expr,val) {if(!(expr)) {return (val);}} diff --git a/dap-sdk/core/src/dap_fnmatch.c b/dap-sdk/core/src/dap_fnmatch.c new file mode 100644 index 0000000000000000000000000000000000000000..21096cf46828208d76ad0e0e54158b6f36eabf37 --- /dev/null +++ b/dap-sdk/core/src/dap_fnmatch.c @@ -0,0 +1,435 @@ +/* Copyright (C) 1991-2020 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C 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.1 of the License, or (at your option) any later version. + + The GNU C 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 + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <assert.h> +#include <errno.h> +#include <ctype.h> +#include <string.h> +#include <stdlib.h> +#include <stdbool.h> +#include "dap_fnmatch.h" + + + +/* For platform which support the ISO C amendement 1 functionality we + support user defined character classes. */ +/* Solaris 2.5 has a bug: <wchar.h> must be included before <wctype.h>. */ +//# include <wchar.h> +//# include <wctype.h> + +# define __libc_use_alloca(n) false +# define alloca_account(len, avar) ((void) (len), (void) (avar), (void *) 0) +# define extend_alloca_account(buf, len, newlen, avar) \ + ((void) (buf), (void) (len), (void) (newlen), (void) (avar), (void *) 0) + + + +/* We need some of the locale data (the collation sequence information) + but there is no interface to get this information in general. Therefore + we support a correct implementation only in glibc. */ +#ifdef _LIBC +# include "../locale/localeinfo.h" +# include "../locale/coll-lookup.h" +# include <shlib-compat.h> + +# define CONCAT(a,b) __CONCAT(a,b) +# define mbsrtowcs __mbsrtowcs +# define fnmatch __fnmatch +extern int fnmatch (const char *pattern, const char *string, int flags); +#endif + +/* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set. */ +#define NO_LEADING_PERIOD(flags) \ + ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD)) + +/* Comment out all this code if we are using the GNU C Library, and are not + actually compiling the library itself. This code is part of the GNU C + Library, but also included in many other GNU distributions. Compiling + and linking in this code is a waste when using the GNU C library + (especially if it is a shared library). Rather than having every GNU + program understand `configure --with-gnu-libc' and omit the object files, + it is simpler to just do this in the source for each such file. */ + +//#if defined _LIBC || !defined __GNU_LIBRARY__ + +# if defined STDC_HEADERS || !defined isascii +# define ISASCII(c) 1 +# else +# define ISASCII(c) isascii(c) +# endif + +# ifdef isblank +# define ISBLANK(c) (ISASCII (c) && isblank (c)) +# else +# define ISBLANK(c) ((c) == ' ' || (c) == '\t') +# endif +# ifdef isgraph +# define ISGRAPH(c) (ISASCII (c) && isgraph (c)) +# else +# define ISGRAPH(c) (ISASCII (c) && isprint (c) && !isspace (c)) +# endif + +# define ISPRINT(c) (ISASCII (c) && isprint (c)) +# define ISDIGIT(c) (ISASCII (c) && isdigit (c)) +# define ISALNUM(c) (ISASCII (c) && isalnum (c)) +# define ISALPHA(c) (ISASCII (c) && isalpha (c)) +# define ISCNTRL(c) (ISASCII (c) && iscntrl (c)) +# define ISLOWER(c) (ISASCII (c) && islower (c)) +# define ISPUNCT(c) (ISASCII (c) && ispunct (c)) +# define ISSPACE(c) (ISASCII (c) && isspace (c)) +# define ISUPPER(c) (ISASCII (c) && isupper (c)) +# define ISXDIGIT(c) (ISASCII (c) && isxdigit (c)) + +# define STREQ(s1, s2) ((strcmp (s1, s2) == 0)) + +# if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) +/* The GNU C library provides support for user-defined character classes + and the functions from ISO C amendement 1. */ +# ifdef CHARCLASS_NAME_MAX +# define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX +# else +/* This shouldn't happen but some implementation might still have this + problem. Use a reasonable default value. */ +# define CHAR_CLASS_MAX_LENGTH 256 +# endif + +# ifdef _LIBC +# define IS_CHAR_CLASS(string) __wctype (string) +# else +# define IS_CHAR_CLASS(string) wctype (string) +# endif + +# ifdef _LIBC +# define ISWCTYPE(WC, WT) __iswctype (WC, WT) +# else +# define ISWCTYPE(WC, WT) iswctype (WC, WT) +# endif + +# if (HAVE_MBSTATE_T && HAVE_MBSRTOWCS) || _LIBC +/* In this case we are implementing the multibyte character handling. */ +# define HANDLE_MULTIBYTE 1 +# endif + +# else +# define CHAR_CLASS_MAX_LENGTH 6 /* Namely, `xdigit'. */ + +# define IS_CHAR_CLASS(string) \ + (STREQ (string, "alpha") || STREQ (string, "upper") \ + || STREQ (string, "lower") || STREQ (string, "digit") \ + || STREQ (string, "alnum") || STREQ (string, "xdigit") \ + || STREQ (string, "space") || STREQ (string, "print") \ + || STREQ (string, "punct") || STREQ (string, "graph") \ + || STREQ (string, "cntrl") || STREQ (string, "blank")) +# endif + + +/* This function doesn't exist on most systems. */ + +# if !defined HAVE___STRCHRNUL && !defined _LIBC +static char * +__strchrnul (const char *s, int c) +{ + char *result = strchr (s, c); + if (result == NULL) + result = strchr (s, '\0'); + return result; +} +# endif + +# if HANDLE_MULTIBYTE && !defined HAVE___STRCHRNUL && !defined _LIBC +static wchar_t * +__wcschrnul (const wchar_t *s, wint_t c) +{ + wchar_t *result = wcschr (s, c); + if (result == NULL) + result = wcschr (s, '\0'); + return result; +} +# endif + +/* Note that this evaluates C many times. */ +# ifdef _LIBC +# define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c)) +# else +# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? tolower (c) : (c)) +# endif +# define FCT internal_fnmatch +# define EXT ext_match +# define END end_pattern +# define STRUCT fnmatch_struct +//# define L(CS) CS +# ifdef _LIBC +# define BTOWC(C) __btowc (C) +# else +# define BTOWC(C) btowc (C) +# endif +# define STRLEN(S) strlen(S) +# define STRCAT(D, S) strcat (D, S) +# define MEMPCPY(D, S, N) __mempcpy (D, S, N) +# define MEMCHR(S, C, N) memchr (S, C, N) +# define STRCOLL(S1, S2) strcoll (S1, S2) +# define WIDE_CHAR_VERSION 0 +//# include <locale/weight.h> +# define FINDIDX findidx +# include "dap_fnmatch_loop.h" + + +# if HANDLE_MULTIBYTE +/* Note that this evaluates C many times. */ +# ifdef _LIBC +# define FOLD(c) ((flags & FNM_CASEFOLD) ? __towlower (c) : (c)) +# else +# define FOLD(c) ((flags & FNM_CASEFOLD) && ISUPPER (c) ? towlower (c) : (c)) +# endif +# define CHAR wchar_t +# define UCHAR wint_t +# define INT wint_t +# define FCT internal_fnwmatch +# define EXT ext_wmatch +# define END end_wpattern +# define STRUCT fnwmatch_struct +# define L(CS) L##CS +# define BTOWC(C) (C) +# define STRLEN(S) __wcslen (S) +# define STRCAT(D, S) __wcscat (D, S) +# define MEMPCPY(D, S, N) __wmempcpy (D, S, N) +# define MEMCHR(S, C, N) __wmemchr (S, C, N) +# define STRCOLL(S1, S2) wcscoll (S1, S2) +# ifdef _LIBC +# define WMEMCMP(S1, S2, N) __wmemcmp (S1, S2, N) +# else +# define WMEMCMP(S1, S2, N) wmemcmp (S1, S2, N) +# endif +# define WIDE_CHAR_VERSION 1 +/* Change the name the header defines so it doesn't conflict with + the <locale/weight.h> version included above. */ +# define findidx findidxwc +# include <locale/weightwc.h> +# undef findidx +# define FINDIDX findidxwc + +# undef IS_CHAR_CLASS +/* We have to convert the wide character string in a multibyte string. But + we know that the character class names consist of alphanumeric characters + from the portable character set, and since the wide character encoding + for a member of the portable character set is the same code point as + its single-byte encoding, we can use a simplified method to convert the + string to a multibyte character string. */ +static wctype_t +is_char_class (const wchar_t *wcs) +{ + char s[CHAR_CLASS_MAX_LENGTH + 1]; + char *cp = s; + + do + { + /* Test for a printable character from the portable character set. */ +# ifdef _LIBC + if (*wcs < 0x20 || *wcs > 0x7e + || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60) + return (wctype_t) 0; +# else + switch (*wcs) + { + case L' ': case L'!': case L'"': case L'#': case L'%': + case L'&': case L'\'': case L'(': case L')': case L'*': + case L'+': case L',': case L'-': case L'.': case L'/': + case L'0': case L'1': case L'2': case L'3': case L'4': + case L'5': case L'6': case L'7': case L'8': case L'9': + case L':': case L';': case L'<': case L'=': case L'>': + case L'?': + case L'A': case L'B': case L'C': case L'D': case L'E': + case L'F': case L'G': case L'H': case L'I': case L'J': + case L'K': case L'L': case L'M': case L'N': case L'O': + case L'P': case L'Q': case L'R': case L'S': case L'T': + case L'U': case L'V': case L'W': case L'X': case L'Y': + case L'Z': + case L'[': case L'\\': case L']': case L'^': case L'_': + case L'a': case L'b': case L'c': case L'd': case L'e': + case L'f': case L'g': case L'h': case L'i': case L'j': + case L'k': case L'l': case L'm': case L'n': case L'o': + case L'p': case L'q': case L'r': case L's': case L't': + case L'u': case L'v': case L'w': case L'x': case L'y': + case L'z': case L'{': case L'|': case L'}': case L'~': + break; + default: + return (wctype_t) 0; + } +# endif + + /* Avoid overrunning the buffer. */ + if (cp == s + CHAR_CLASS_MAX_LENGTH) + return (wctype_t) 0; + + *cp++ = (char) *wcs++; + } + while (*wcs != L'\0'); + + *cp = '\0'; + +# ifdef _LIBC + return __wctype (s); +# else + return wctype (s); +# endif +} +# define IS_CHAR_CLASS(string) is_char_class (string) + +# include "fnmatch_loop.c" +# endif + + +int dap_fnmatch (const char *pattern, const char *string, int flags) +{ +# if HANDLE_MULTIBYTE + if (__builtin_expect (MB_CUR_MAX, 1) != 1) + { + mbstate_t ps; + size_t n; + const char *p; + wchar_t *wpattern_malloc = NULL; + wchar_t *wpattern; + wchar_t *wstring_malloc = NULL; + wchar_t *wstring; + size_t alloca_used = 0; + + /* Convert the strings into wide characters. */ + memset (&ps, '\0', sizeof (ps)); + p = pattern; +#ifdef _LIBC + n = __strnlen (pattern, 1024); +#else + n = strlen (pattern); +#endif + if (__glibc_likely (n < 1024)) + { + wpattern = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t), + alloca_used); + n = mbsrtowcs (wpattern, &p, n + 1, &ps); + if (__glibc_unlikely (n == (size_t) -1)) + /* Something wrong. + XXX Do we have to set `errno' to something which mbsrtows hasn't + already done? */ + return -1; + if (p) + { + memset (&ps, '\0', sizeof (ps)); + goto prepare_wpattern; + } + } + else + { + prepare_wpattern: + n = mbsrtowcs (NULL, &pattern, 0, &ps); + if (__glibc_unlikely (n == (size_t) -1)) + /* Something wrong. + XXX Do we have to set `errno' to something which mbsrtows hasn't + already done? */ + return -1; + if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t))) + { + __set_errno (ENOMEM); + return -2; + } + wpattern_malloc = wpattern + = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t)); + assert (mbsinit (&ps)); + if (wpattern == NULL) + return -2; + (void) mbsrtowcs (wpattern, &pattern, n + 1, &ps); + } + + assert (mbsinit (&ps)); +#ifdef _LIBC + n = __strnlen (string, 1024); +#else + n = strlen (string); +#endif + p = string; + if (__glibc_likely (n < 1024)) + { + wstring = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t), + alloca_used); + n = mbsrtowcs (wstring, &p, n + 1, &ps); + if (__glibc_unlikely (n == (size_t) -1)) + { + /* Something wrong. + XXX Do we have to set `errno' to something which + mbsrtows hasn't already done? */ + free_return: + free (wpattern_malloc); + return -1; + } + if (p) + { + memset (&ps, '\0', sizeof (ps)); + goto prepare_wstring; + } + } + else + { + prepare_wstring: + n = mbsrtowcs (NULL, &string, 0, &ps); + if (__glibc_unlikely (n == (size_t) -1)) + /* Something wrong. + XXX Do we have to set `errno' to something which mbsrtows hasn't + already done? */ + goto free_return; + if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t))) + { + free (wpattern_malloc); + __set_errno (ENOMEM); + return -2; + } + + wstring_malloc = wstring + = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t)); + if (wstring == NULL) + { + free (wpattern_malloc); + return -2; + } + assert (mbsinit (&ps)); + (void) mbsrtowcs (wstring, &string, n + 1, &ps); + } + + int res = internal_fnwmatch (wpattern, wstring, wstring + n, + flags & FNM_PERIOD, flags, NULL, + alloca_used); + + free (wstring_malloc); + free (wpattern_malloc); + + return res; + } +# endif /* mbstate_t and mbsrtowcs or _LIBC. */ + + return internal_fnmatch (pattern, string, string + strlen (string), + flags & FNM_PERIOD, flags, NULL, 0); +} + +# ifdef _LIBC +# undef fnmatch +versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3); +# if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3) +strong_alias (__fnmatch, __fnmatch_old) +compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0); +# endif +libc_hidden_ver (__fnmatch, fnmatch) +# endif + +//#endif /* _LIBC or not __GNU_LIBRARY__. */ diff --git a/modules/global-db/dap_chain_global_db_driver_cdb.c b/modules/global-db/dap_chain_global_db_driver_cdb.c index 88221e95d522ec66d094e9a1011ea756c765a9ea..5adb80c769556202b7ef59097e40dbfd349b38b6 100644 --- a/modules/global-db/dap_chain_global_db_driver_cdb.c +++ b/modules/global-db/dap_chain_global_db_driver_cdb.c @@ -32,7 +32,7 @@ #include "dap_common.h" #include "dap_hash.h" -#include "dap_strfuncs.h" +#include "dap_strfuncs.h" // #include <dap_fnmatch.h> #include "dap_chain_global_db_driver_cdb.h" #include "dap_file_utils.h" @@ -471,11 +471,9 @@ dap_list_t* dap_db_driver_cdb_get_groups_by_mask(const char *a_group_mask) pthread_mutex_lock(&cdb_mutex); HASH_ITER(hh, s_cdb, cur_cdb, tmp) { - if(strstr(cur_cdb->local_group, a_group_mask)) { - if(!strstr(cur_cdb->local_group, ".del")) { + if(!dap_fnmatch(a_group_mask, cur_cdb->local_group, 0)) + if(dap_fnmatch("*.del", cur_cdb->local_group, 0)) l_ret_list = dap_list_prepend(l_ret_list, dap_strdup(cur_cdb->local_group)); - } - } } pthread_mutex_unlock(&cdb_mutex); return l_ret_list; diff --git a/modules/net/dap_chain_net.c b/modules/net/dap_chain_net.c index b53d161851272715acfbd852c6fb8a878afaadc1..2d70ab3709012f55d86fe2dca1ed3efb534bd70e 100644 --- a/modules/net/dap_chain_net.c +++ b/modules/net/dap_chain_net.c @@ -1352,7 +1352,7 @@ int s_net_load(const char * a_net_name) while(l_groups) { char *l_group_name = l_groups->data; // do not use groups with names like *.del - if(!strstr(l_group_name, ".del")) { + if(dap_fnmatch("*.del", l_group_name, 0)) { const char *l_history_group = dap_chain_global_db_add_history_extra_group(l_group_name, PVT(l_net)->gdb_sync_nodes_addrs, &PVT(l_net)->gdb_sync_nodes_addrs_count); diff --git a/modules/service/vpn/dap_chain_net_srv_vpn_cdb_auth.c b/modules/service/vpn/dap_chain_net_srv_vpn_cdb_auth.c index 7cb35668c6f5b2c63d5ffdfa118a0616ebfb7946..587121d1ab83328fc9c6c1fd73491333bb675ea5 100644 --- a/modules/service/vpn/dap_chain_net_srv_vpn_cdb_auth.c +++ b/modules/service/vpn/dap_chain_net_srv_vpn_cdb_auth.c @@ -282,47 +282,56 @@ int dap_chain_net_srv_vpn_cdb_auth_activate_serial(const char * a_serial_raw, co int l_res = 0; byte_t *l_pkey_raw = NULL; size_t l_pkey_raw_size = 0; + dap_enc_key_type_t l_key_type; { - // deserealize pkey + // verify sign + byte_t *l_sign_raw = NULL; + size_t l_sign_length = dap_strlen(a_sign); + l_sign_raw = DAP_NEW_Z_SIZE(byte_t, l_sign_length * 2); + size_t l_sign_raw_size = dap_enc_base64_decode(a_sign, l_sign_length, l_sign_raw, DAP_ENC_DATA_TYPE_B64_URLSAFE); + dap_sign_t *l_sign = (dap_sign_t*) l_sign_raw; //dap_sign_pack(l_client_key, l_sign_raw, l_sign_raw_size, l_pkey_raw, l_pkey_length); + //get key type for pkey + dap_sign_type_t l_chain_sign_type; + l_chain_sign_type.raw = l_sign_raw_size > 0 ? l_sign->header.type.raw : SIG_TYPE_NULL; + l_key_type = dap_sign_type_to_key_type(l_chain_sign_type); + size_t l_serial_len = dap_strlen(a_serial_raw); + l_res = dap_sign_verify(l_sign, a_serial_raw, l_serial_len); + if(!l_res){ + DAP_DELETE(l_sign_raw); + return -2;//OP_CODE_LOGIN_INCORRECT_SIGN + } + + // deserialize pkey dap_enc_key_t *l_client_key = NULL; size_t l_pkey_length = dap_strlen(a_pkey); l_pkey_raw = DAP_NEW_Z_SIZE(byte_t, l_pkey_length); memset(l_pkey_raw, 0, l_pkey_length); l_pkey_raw_size = dap_enc_base64_decode(a_pkey, l_pkey_length, l_pkey_raw, DAP_ENC_DATA_TYPE_B64_URLSAFE); - l_client_key = dap_enc_key_new(DAP_ENC_KEY_TYPE_SIG_TESLA); + l_client_key = dap_enc_key_new(l_key_type); //DAP_ENC_KEY_TYPE_SIG_TESLA l_res = dap_enc_key_deserealize_pub_key(l_client_key, l_pkey_raw, l_pkey_raw_size); - // verify sign - if(!l_res) { - byte_t *l_sign_raw = NULL; - size_t l_sign_length = dap_strlen(a_sign); - l_sign_raw = DAP_NEW_Z_SIZE(byte_t, l_sign_length*2); - size_t l_sign_raw_size = dap_enc_base64_decode(a_sign, l_sign_length, l_sign_raw, DAP_ENC_DATA_TYPE_B64_URLSAFE); - dap_sign_t *l_sign = (dap_sign_t*)l_sign_raw;//dap_sign_pack(l_client_key, l_sign_raw, l_sign_raw_size, l_pkey_raw, l_pkey_length); - size_t as = dap_sign_get_size(l_sign); - size_t l_serial_len = dap_strlen(a_serial_raw); - l_res = dap_sign_verify(l_sign, a_serial_raw, l_serial_len); - DAP_DELETE(l_sign_raw); - } - //dap_enc_key_deserealize_sign - } - - // activate serial key - if(l_res==1) { - // added pkey to serial - l_serial_key->header.ext_size = l_pkey_raw_size; - l_serial_key = DAP_REALLOC(l_serial_key,dap_serial_key_len(l_serial_key)); - l_serial_key->header.activated = time(NULL); - memcpy(l_serial_key->ext, l_pkey_raw, l_pkey_raw_size); - // save updated serial - if(dap_chain_global_db_gr_set(dap_strdup(l_serial_key->header.serial), l_serial_key, - dap_serial_key_len(l_serial_key), - s_group_serials_activated)) { - dap_chain_global_db_gr_del(l_serial_key->header.serial, s_group_serials); - l_ret = 0;// OK + // pkey from sign + size_t l_pkey_sign_size = 0; + uint8_t *l_pkey_sign = dap_sign_get_pkey(l_sign, &l_pkey_sign_size); + // activate serial key + if(l_pkey_sign_size == l_pkey_raw_size && !memcmp(l_pkey_sign, l_pkey_raw, l_pkey_sign_size)) { + // added pkey to serial + l_serial_key->header.ext_size = l_pkey_raw_size; + l_serial_key = DAP_REALLOC(l_serial_key, dap_serial_key_len(l_serial_key)); + l_serial_key->header.activated = time(NULL); + l_serial_key->header.os = l_key_type; + memcpy(l_serial_key->ext, l_pkey_raw, l_pkey_raw_size); + // save updated serial + if(dap_chain_global_db_gr_set(dap_strdup(l_serial_key->header.serial), l_serial_key, + dap_serial_key_len(l_serial_key), + s_group_serials_activated)) { + dap_chain_global_db_gr_del(l_serial_key->header.serial, s_group_serials); + l_ret = 0; // OK + } } - } - else{ - return -2;//OP_CODE_LOGIN_INCORRECT_SIGN + // bad pkey + else + l_ret = -2;//OP_CODE_LOGIN_INCORRECT_SIGN + DAP_DELETE(l_sign_raw); } DAP_DELETE(l_pkey_raw); } @@ -352,7 +361,20 @@ int dap_chain_net_srv_vpn_cdb_auth_check_serial(const char * a_serial, const cha if((l_serial_key->header.activated + l_serial_key->header.expired) < time(NULL)) l_ret = -4; } - DAP_DELETE(l_serial_key); + // check pkey + dap_enc_key_t *l_client_key = NULL; + size_t l_pkey_length = dap_strlen(a_pkey_b64); + byte_t *l_pkey_raw = DAP_NEW_Z_SIZE(byte_t, l_pkey_length); + memset(l_pkey_raw, 0, l_pkey_length); + size_t l_pkey_raw_size = dap_enc_base64_decode(a_pkey_b64, l_pkey_length, l_pkey_raw, DAP_ENC_DATA_TYPE_B64_URLSAFE); + // pkey from sign + size_t l_pkey_sign_size = l_serial_key->header.ext_size; + uint8_t *l_pkey_sign = l_serial_key->ext; + // compare pkeys + if(l_pkey_sign_size != l_pkey_raw_size || memcmp(l_pkey_sign, l_pkey_raw, l_pkey_sign_size)) { + l_ret = -2; + } + DAP_DELETE(l_pkey_raw); return l_ret; } @@ -1091,10 +1113,10 @@ static void s_http_enc_proc(enc_http_delegate_t *a_delegate, void * a_arg) enc_http_reply_f(a_delegate, OP_CODE_NOT_FOUND_LOGIN_IN_DB); *l_return_code = Http_Status_OK; break; - /*case -2: - enc_http_reply_f(a_delegate, OP_CODE_LOGIN_INCORRECT_PSWD); + case -2: + enc_http_reply_f(a_delegate, OP_CODE_LOGIN_INCORRECT_SIGN);// incorrect pkey *l_return_code = Http_Status_OK; - break;*/ + break; case -3: enc_http_reply_f(a_delegate, OP_CODE_LOGIN_INACTIVE); *l_return_code = Http_Status_OK;