diff options
Diffstat (limited to 'posix')
-rw-r--r-- | posix/Versions | 4 | ||||
-rw-r--r-- | posix/fnmatch.c | 16 | ||||
-rw-r--r-- | posix/fnmatch_loop.c | 39 | ||||
-rw-r--r-- | posix/tst-fnmatch.input | 1 |
4 files changed, 39 insertions, 21 deletions
diff --git a/posix/Versions b/posix/Versions index 0d04fccc22..a302f7bed3 100644 --- a/posix/Versions +++ b/posix/Versions @@ -109,4 +109,8 @@ libc { # Used in macros. __sysconf; } + GLIBC_2.2.3 { + # Extended Interface. + fnmatch; + } } diff --git a/posix/fnmatch.c b/posix/fnmatch.c index 98c5ffc5ca..df4311a79c 100644 --- a/posix/fnmatch.c +++ b/posix/fnmatch.c @@ -55,10 +55,13 @@ # include "../locale/localeinfo.h" # include "../locale/elem-hash.h" # include "../locale/coll-lookup.h" +# include <shlib-compat.h> # define CONCAT(a,b) __CONCAT(a,b) # define mbsinit __mbsinit # 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. */ @@ -212,6 +215,8 @@ __wcschrnul (s, 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) @@ -233,6 +238,8 @@ __wcschrnul (s, c) # define END end_wpattern # 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) @@ -355,4 +362,13 @@ fnmatch (pattern, string, flags) flags & FNM_PERIOD, flags); } +# 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 +# endif + #endif /* _LIBC or not __GNU_LIBRARY__. */ diff --git a/posix/fnmatch_loop.c b/posix/fnmatch_loop.c index e9c7af2b7e..940073412e 100644 --- a/posix/fnmatch_loop.c +++ b/posix/fnmatch_loop.c @@ -1011,6 +1011,7 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end, CHAR str[0]; } *list = NULL; struct patternlist **lastp = &list; + size_t pattern_len = STRLEN (pattern); const CHAR *p; const CHAR *rs; @@ -1049,9 +1050,14 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end, { /* This means we found the end of the pattern. */ #define NEW_PATTERN \ - struct patternlist *newp = alloca (sizeof (struct patternlist) \ - + ((p - startp + 1) \ - * sizeof (CHAR))); \ + struct patternlist *newp; \ + \ + if (opt == L('?') || opt == L('@')) \ + newp = alloca (sizeof (struct patternlist) \ + + (pattern_len * sizeof (CHAR))); \ + else \ + newp = alloca (sizeof (struct patternlist) \ + + ((p - startp + 1) * sizeof (CHAR))); \ *((CHAR *) MEMPCPY (newp->str, startp, p - startp)) = L('\0'); \ newp->next = NULL; \ *lastp = newp; \ @@ -1117,24 +1123,15 @@ EXT (INT opt, const CHAR *pattern, const CHAR *string, const CHAR *string_end, case L('@'): 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) == 0 - /* This was successful. Now match the rest of the strings - 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) == 0)) - /* It worked. Signal success. */ - return 0; - } + /* 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) == 0) + /* It worked. Signal success. */ + return 0; while ((list = list->next) != NULL); /* None of the patterns lead to a match. */ diff --git a/posix/tst-fnmatch.input b/posix/tst-fnmatch.input index 6ae0a2aa82..219124556e 100644 --- a/posix/tst-fnmatch.input +++ b/posix/tst-fnmatch.input @@ -714,3 +714,4 @@ C "]" "!([!]a[])" 0 EXTMATCH C ")" "*([)])" 0 EXTMATCH C "*" "*([*(])" 0 EXTMATCH C "abcd" "*!(|a)cd" NOMATCH EXTMATCH +C "ab/.a" "+([abc])/*" NOMATCH EXTMATCH|PATHNAME|PERIOD |