Home | History | Annotate | Line # | Download | only in import
fnmatch.c revision 1.1
      1  1.1  christos /* Copyright (C) 1991-2020 Free Software Foundation, Inc.
      2  1.1  christos    This file is part of the GNU C Library.
      3  1.1  christos 
      4  1.1  christos    The GNU C Library is free software; you can redistribute it and/or
      5  1.1  christos    modify it under the terms of the GNU General Public
      6  1.1  christos    License as published by the Free Software Foundation; either
      7  1.1  christos    version 3 of the License, or (at your option) any later version.
      8  1.1  christos 
      9  1.1  christos    The GNU C Library is distributed in the hope that it will be useful,
     10  1.1  christos    but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  1.1  christos    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     12  1.1  christos    General Public License for more details.
     13  1.1  christos 
     14  1.1  christos    You should have received a copy of the GNU General Public
     15  1.1  christos    License along with the GNU C Library; if not, see
     16  1.1  christos    <https://www.gnu.org/licenses/>.  */
     17  1.1  christos 
     18  1.1  christos #ifndef _LIBC
     19  1.1  christos # include <libc-config.h>
     20  1.1  christos #endif
     21  1.1  christos 
     22  1.1  christos /* Enable GNU extensions in fnmatch.h.  */
     23  1.1  christos #ifndef _GNU_SOURCE
     24  1.1  christos # define _GNU_SOURCE    1
     25  1.1  christos #endif
     26  1.1  christos 
     27  1.1  christos #include <fnmatch.h>
     28  1.1  christos 
     29  1.1  christos #include <assert.h>
     30  1.1  christos #include <errno.h>
     31  1.1  christos #include <ctype.h>
     32  1.1  christos #include <string.h>
     33  1.1  christos #include <stdlib.h>
     34  1.1  christos #if defined _LIBC || HAVE_ALLOCA
     35  1.1  christos # include <alloca.h>
     36  1.1  christos #endif
     37  1.1  christos #include <wchar.h>
     38  1.1  christos #include <wctype.h>
     39  1.1  christos #include <stddef.h>
     40  1.1  christos #include <stdbool.h>
     41  1.1  christos 
     42  1.1  christos /* We need some of the locale data (the collation sequence information)
     43  1.1  christos    but there is no interface to get this information in general.  Therefore
     44  1.1  christos    we support a correct implementation only in glibc.  */
     45  1.1  christos #ifdef _LIBC
     46  1.1  christos # include "../locale/localeinfo.h"
     47  1.1  christos # include "../locale/coll-lookup.h"
     48  1.1  christos # include <shlib-compat.h>
     49  1.1  christos 
     50  1.1  christos # define CONCAT(a,b) __CONCAT(a,b)
     51  1.1  christos # define btowc __btowc
     52  1.1  christos # define iswctype __iswctype
     53  1.1  christos # define mbsrtowcs __mbsrtowcs
     54  1.1  christos # define mempcpy __mempcpy
     55  1.1  christos # define strnlen __strnlen
     56  1.1  christos # define towlower __towlower
     57  1.1  christos # define wcscat __wcscat
     58  1.1  christos # define wcslen __wcslen
     59  1.1  christos # define wctype __wctype
     60  1.1  christos # define wmemchr __wmemchr
     61  1.1  christos # define wmempcpy __wmempcpy
     62  1.1  christos # define fnmatch __fnmatch
     63  1.1  christos extern int fnmatch (const char *pattern, const char *string, int flags);
     64  1.1  christos #endif
     65  1.1  christos 
     66  1.1  christos #ifdef _LIBC
     67  1.1  christos # if __GNUC__ < 7
     68  1.1  christos #  define FALLTHROUGH ((void) 0)
     69  1.1  christos # else
     70  1.1  christos #  define FALLTHROUGH __attribute__ ((__fallthrough__))
     71  1.1  christos # endif
     72  1.1  christos #else
     73  1.1  christos # include "attribute.h"
     74  1.1  christos #endif
     75  1.1  christos 
     76  1.1  christos #include <intprops.h>
     77  1.1  christos #include <flexmember.h>
     78  1.1  christos 
     79  1.1  christos /* We often have to test for FNM_FILE_NAME and FNM_PERIOD being both set.  */
     80  1.1  christos #define NO_LEADING_PERIOD(flags) \
     81  1.1  christos   ((flags & (FNM_FILE_NAME | FNM_PERIOD)) == (FNM_FILE_NAME | FNM_PERIOD))
     82  1.1  christos 
     83  1.1  christos #ifndef _LIBC
     84  1.1  christos # if HAVE_ALLOCA
     85  1.1  christos /* The OS usually guarantees only one guard page at the bottom of the stack,
     86  1.1  christos    and a page size can be as small as 4096 bytes.  So we cannot safely
     87  1.1  christos    allocate anything larger than 4096 bytes.  Also care for the possibility
     88  1.1  christos    of a few compiler-allocated temporary stack slots.  */
     89  1.1  christos #  define __libc_use_alloca(n) ((n) < 4032)
     90  1.1  christos # else
     91  1.1  christos /* Just use malloc.  */
     92  1.1  christos #  define __libc_use_alloca(n) false
     93  1.1  christos #  undef alloca
     94  1.1  christos #  define alloca(n) malloc (n)
     95  1.1  christos # endif
     96  1.1  christos # define alloca_account(size, avar) ((avar) += (size), alloca (size))
     97  1.1  christos #endif
     98  1.1  christos 
     99  1.1  christos /* Provide support for user-defined character classes, based on the functions
    100  1.1  christos    from ISO C 90 amendment 1.  */
    101  1.1  christos #ifdef CHARCLASS_NAME_MAX
    102  1.1  christos # define CHAR_CLASS_MAX_LENGTH CHARCLASS_NAME_MAX
    103  1.1  christos #else
    104  1.1  christos /* This shouldn't happen but some implementation might still have this
    105  1.1  christos    problem.  Use a reasonable default value.  */
    106  1.1  christos # define CHAR_CLASS_MAX_LENGTH 256
    107  1.1  christos #endif
    108  1.1  christos 
    109  1.1  christos #define IS_CHAR_CLASS(string) wctype (string)
    110  1.1  christos 
    111  1.1  christos /* Avoid depending on library functions or files
    112  1.1  christos    whose names are inconsistent.  */
    113  1.1  christos 
    114  1.1  christos /* Global variable.  */
    115  1.1  christos static int posixly_correct;
    116  1.1  christos 
    117  1.1  christos /* Note that this evaluates C many times.  */
    118  1.1  christos #define FOLD(c) ((flags & FNM_CASEFOLD) ? tolower (c) : (c))
    119  1.1  christos #define CHAR    char
    120  1.1  christos #define UCHAR   unsigned char
    121  1.1  christos #define INT     int
    122  1.1  christos #define FCT     internal_fnmatch
    123  1.1  christos #define EXT     ext_match
    124  1.1  christos #define END     end_pattern
    125  1.1  christos #define STRUCT  fnmatch_struct
    126  1.1  christos #define L_(CS)  CS
    127  1.1  christos #define BTOWC(C) btowc (C)
    128  1.1  christos #define STRLEN(S) strlen (S)
    129  1.1  christos #define STRCAT(D, S) strcat (D, S)
    130  1.1  christos #define MEMPCPY(D, S, N) mempcpy (D, S, N)
    131  1.1  christos #define MEMCHR(S, C, N) memchr (S, C, N)
    132  1.1  christos #define WIDE_CHAR_VERSION 0
    133  1.1  christos #ifdef _LIBC
    134  1.1  christos # include <locale/weight.h>
    135  1.1  christos # define FINDIDX findidx
    136  1.1  christos #endif
    137  1.1  christos #include "fnmatch_loop.c"
    138  1.1  christos 
    139  1.1  christos 
    140  1.1  christos #define FOLD(c) ((flags & FNM_CASEFOLD) ? towlower (c) : (c))
    141  1.1  christos #define CHAR    wchar_t
    142  1.1  christos #define UCHAR   wint_t
    143  1.1  christos #define INT     wint_t
    144  1.1  christos #define FCT     internal_fnwmatch
    145  1.1  christos #define EXT     ext_wmatch
    146  1.1  christos #define END     end_wpattern
    147  1.1  christos #define L_(CS)  L##CS
    148  1.1  christos #define BTOWC(C) (C)
    149  1.1  christos #define STRLEN(S) wcslen (S)
    150  1.1  christos #define STRCAT(D, S) wcscat (D, S)
    151  1.1  christos #define MEMPCPY(D, S, N) wmempcpy (D, S, N)
    152  1.1  christos #define MEMCHR(S, C, N) wmemchr (S, C, N)
    153  1.1  christos #define WIDE_CHAR_VERSION 1
    154  1.1  christos #ifdef _LIBC
    155  1.1  christos /* Change the name the header defines so it doesn't conflict with
    156  1.1  christos    the <locale/weight.h> version included above.  */
    157  1.1  christos # define findidx findidxwc
    158  1.1  christos # include <locale/weightwc.h>
    159  1.1  christos # undef findidx
    160  1.1  christos # define FINDIDX findidxwc
    161  1.1  christos #endif
    162  1.1  christos 
    163  1.1  christos #undef IS_CHAR_CLASS
    164  1.1  christos /* We have to convert the wide character string in a multibyte string.  But
    165  1.1  christos    we know that the character class names consist of alphanumeric characters
    166  1.1  christos    from the portable character set, and since the wide character encoding
    167  1.1  christos    for a member of the portable character set is the same code point as
    168  1.1  christos    its single-byte encoding, we can use a simplified method to convert the
    169  1.1  christos    string to a multibyte character string.  */
    170  1.1  christos static wctype_t
    171  1.1  christos is_char_class (const wchar_t *wcs)
    172  1.1  christos {
    173  1.1  christos   char s[CHAR_CLASS_MAX_LENGTH + 1];
    174  1.1  christos   char *cp = s;
    175  1.1  christos 
    176  1.1  christos   do
    177  1.1  christos     {
    178  1.1  christos       /* Test for a printable character from the portable character set.  */
    179  1.1  christos #ifdef _LIBC
    180  1.1  christos       if (*wcs < 0x20 || *wcs > 0x7e
    181  1.1  christos           || *wcs == 0x24 || *wcs == 0x40 || *wcs == 0x60)
    182  1.1  christos         return (wctype_t) 0;
    183  1.1  christos #else
    184  1.1  christos       switch (*wcs)
    185  1.1  christos         {
    186  1.1  christos         case L' ': case L'!': case L'"': case L'#': case L'%':
    187  1.1  christos         case L'&': case L'\'': case L'(': case L')': case L'*':
    188  1.1  christos         case L'+': case L',': case L'-': case L'.': case L'/':
    189  1.1  christos         case L'0': case L'1': case L'2': case L'3': case L'4':
    190  1.1  christos         case L'5': case L'6': case L'7': case L'8': case L'9':
    191  1.1  christos         case L':': case L';': case L'<': case L'=': case L'>':
    192  1.1  christos         case L'?':
    193  1.1  christos         case L'A': case L'B': case L'C': case L'D': case L'E':
    194  1.1  christos         case L'F': case L'G': case L'H': case L'I': case L'J':
    195  1.1  christos         case L'K': case L'L': case L'M': case L'N': case L'O':
    196  1.1  christos         case L'P': case L'Q': case L'R': case L'S': case L'T':
    197  1.1  christos         case L'U': case L'V': case L'W': case L'X': case L'Y':
    198  1.1  christos         case L'Z':
    199  1.1  christos         case L'[': case L'\\': case L']': case L'^': case L'_':
    200  1.1  christos         case L'a': case L'b': case L'c': case L'd': case L'e':
    201  1.1  christos         case L'f': case L'g': case L'h': case L'i': case L'j':
    202  1.1  christos         case L'k': case L'l': case L'm': case L'n': case L'o':
    203  1.1  christos         case L'p': case L'q': case L'r': case L's': case L't':
    204  1.1  christos         case L'u': case L'v': case L'w': case L'x': case L'y':
    205  1.1  christos         case L'z': case L'{': case L'|': case L'}': case L'~':
    206  1.1  christos           break;
    207  1.1  christos         default:
    208  1.1  christos           return (wctype_t) 0;
    209  1.1  christos         }
    210  1.1  christos #endif
    211  1.1  christos 
    212  1.1  christos       /* Avoid overrunning the buffer.  */
    213  1.1  christos       if (cp == s + CHAR_CLASS_MAX_LENGTH)
    214  1.1  christos         return (wctype_t) 0;
    215  1.1  christos 
    216  1.1  christos       *cp++ = (char) *wcs++;
    217  1.1  christos     }
    218  1.1  christos   while (*wcs != L'\0');
    219  1.1  christos 
    220  1.1  christos   *cp = '\0';
    221  1.1  christos 
    222  1.1  christos   return wctype (s);
    223  1.1  christos }
    224  1.1  christos #define IS_CHAR_CLASS(string) is_char_class (string)
    225  1.1  christos 
    226  1.1  christos #include "fnmatch_loop.c"
    227  1.1  christos 
    228  1.1  christos 
    229  1.1  christos int
    230  1.1  christos fnmatch (const char *pattern, const char *string, int flags)
    231  1.1  christos {
    232  1.1  christos   if (__glibc_unlikely (MB_CUR_MAX != 1))
    233  1.1  christos     {
    234  1.1  christos       mbstate_t ps;
    235  1.1  christos       size_t n;
    236  1.1  christos       const char *p;
    237  1.1  christos       wchar_t *wpattern_malloc = NULL;
    238  1.1  christos       wchar_t *wpattern;
    239  1.1  christos       wchar_t *wstring_malloc = NULL;
    240  1.1  christos       wchar_t *wstring;
    241  1.1  christos       size_t alloca_used = 0;
    242  1.1  christos 
    243  1.1  christos       /* Convert the strings into wide characters.  */
    244  1.1  christos       memset (&ps, '\0', sizeof (ps));
    245  1.1  christos       p = pattern;
    246  1.1  christos       n = strnlen (pattern, 1024);
    247  1.1  christos       if (__glibc_likely (n < 1024))
    248  1.1  christos         {
    249  1.1  christos           wpattern = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t),
    250  1.1  christos                                                  alloca_used);
    251  1.1  christos           n = mbsrtowcs (wpattern, &p, n + 1, &ps);
    252  1.1  christos           if (__glibc_unlikely (n == (size_t) -1))
    253  1.1  christos             /* Something wrong.
    254  1.1  christos                XXX Do we have to set 'errno' to something which mbsrtows hasn't
    255  1.1  christos                already done?  */
    256  1.1  christos             return -1;
    257  1.1  christos           if (p)
    258  1.1  christos             {
    259  1.1  christos               memset (&ps, '\0', sizeof (ps));
    260  1.1  christos               goto prepare_wpattern;
    261  1.1  christos             }
    262  1.1  christos         }
    263  1.1  christos       else
    264  1.1  christos         {
    265  1.1  christos         prepare_wpattern:
    266  1.1  christos           n = mbsrtowcs (NULL, &pattern, 0, &ps);
    267  1.1  christos           if (__glibc_unlikely (n == (size_t) -1))
    268  1.1  christos             /* Something wrong.
    269  1.1  christos                XXX Do we have to set 'errno' to something which mbsrtows hasn't
    270  1.1  christos                already done?  */
    271  1.1  christos             return -1;
    272  1.1  christos           if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t)))
    273  1.1  christos             {
    274  1.1  christos               __set_errno (ENOMEM);
    275  1.1  christos               return -2;
    276  1.1  christos             }
    277  1.1  christos           wpattern_malloc = wpattern
    278  1.1  christos             = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t));
    279  1.1  christos           assert (mbsinit (&ps));
    280  1.1  christos           if (wpattern == NULL)
    281  1.1  christos             return -2;
    282  1.1  christos           (void) mbsrtowcs (wpattern, &pattern, n + 1, &ps);
    283  1.1  christos         }
    284  1.1  christos 
    285  1.1  christos       assert (mbsinit (&ps));
    286  1.1  christos       n = strnlen (string, 1024);
    287  1.1  christos       p = string;
    288  1.1  christos       if (__glibc_likely (n < 1024))
    289  1.1  christos         {
    290  1.1  christos           wstring = (wchar_t *) alloca_account ((n + 1) * sizeof (wchar_t),
    291  1.1  christos                                                 alloca_used);
    292  1.1  christos           n = mbsrtowcs (wstring, &p, n + 1, &ps);
    293  1.1  christos           if (__glibc_unlikely (n == (size_t) -1))
    294  1.1  christos             {
    295  1.1  christos               /* Something wrong.
    296  1.1  christos                  XXX Do we have to set 'errno' to something which
    297  1.1  christos                  mbsrtows hasn't already done?  */
    298  1.1  christos             free_return:
    299  1.1  christos               free (wpattern_malloc);
    300  1.1  christos               return -1;
    301  1.1  christos             }
    302  1.1  christos           if (p)
    303  1.1  christos             {
    304  1.1  christos               memset (&ps, '\0', sizeof (ps));
    305  1.1  christos               goto prepare_wstring;
    306  1.1  christos             }
    307  1.1  christos         }
    308  1.1  christos       else
    309  1.1  christos         {
    310  1.1  christos         prepare_wstring:
    311  1.1  christos           n = mbsrtowcs (NULL, &string, 0, &ps);
    312  1.1  christos           if (__glibc_unlikely (n == (size_t) -1))
    313  1.1  christos             /* Something wrong.
    314  1.1  christos                XXX Do we have to set 'errno' to something which mbsrtows hasn't
    315  1.1  christos                already done?  */
    316  1.1  christos             goto free_return;
    317  1.1  christos           if (__glibc_unlikely (n >= (size_t) -1 / sizeof (wchar_t)))
    318  1.1  christos             {
    319  1.1  christos               free (wpattern_malloc);
    320  1.1  christos               __set_errno (ENOMEM);
    321  1.1  christos               return -2;
    322  1.1  christos             }
    323  1.1  christos 
    324  1.1  christos           wstring_malloc = wstring
    325  1.1  christos             = (wchar_t *) malloc ((n + 1) * sizeof (wchar_t));
    326  1.1  christos           if (wstring == NULL)
    327  1.1  christos             {
    328  1.1  christos               free (wpattern_malloc);
    329  1.1  christos               return -2;
    330  1.1  christos             }
    331  1.1  christos           assert (mbsinit (&ps));
    332  1.1  christos           (void) mbsrtowcs (wstring, &string, n + 1, &ps);
    333  1.1  christos         }
    334  1.1  christos 
    335  1.1  christos       int res = internal_fnwmatch (wpattern, wstring, wstring + n,
    336  1.1  christos                                    flags & FNM_PERIOD, flags, NULL,
    337  1.1  christos                                    alloca_used);
    338  1.1  christos 
    339  1.1  christos       free (wstring_malloc);
    340  1.1  christos       free (wpattern_malloc);
    341  1.1  christos 
    342  1.1  christos       return res;
    343  1.1  christos     }
    344  1.1  christos 
    345  1.1  christos   return internal_fnmatch (pattern, string, string + strlen (string),
    346  1.1  christos                            flags & FNM_PERIOD, flags, NULL, 0);
    347  1.1  christos }
    348  1.1  christos 
    349  1.1  christos #undef fnmatch
    350  1.1  christos versioned_symbol (libc, __fnmatch, fnmatch, GLIBC_2_2_3);
    351  1.1  christos #if SHLIB_COMPAT(libc, GLIBC_2_0, GLIBC_2_2_3)
    352  1.1  christos strong_alias (__fnmatch, __fnmatch_old)
    353  1.1  christos compat_symbol (libc, __fnmatch_old, fnmatch, GLIBC_2_0);
    354  1.1  christos #endif
    355  1.1  christos libc_hidden_ver (__fnmatch, fnmatch)
    356