From: Greg Hudson Date: Mon, 5 Sep 2011 16:26:25 +0000 (+0000) Subject: Add fnmatch support to libkrb5support X-Git-Tag: krb5-1.10-alpha1~222 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=ca474e3041b3916d65ea8c3383da03de71c2405a;p=krb5.git Add fnmatch support to libkrb5support git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@25153 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/src/configure.in b/src/configure.in index 5d3f5264d..c765c91e3 100644 --- a/src/configure.in +++ b/src/configure.in @@ -76,13 +76,29 @@ AC_CHECK_HEADER(libintl.h, [ AC_SUBST(po) # for kdc -AC_CHECK_HEADERS(syslog.h sys/sockio.h ifaddrs.h unistd.h) +AC_CHECK_HEADERS(syslog.h sys/sockio.h ifaddrs.h unistd.h fnmatch.h) AC_CHECK_FUNCS(openlog syslog closelog strftime vsprintf vasprintf vsnprintf) -AC_CHECK_FUNCS(strlcpy) +AC_CHECK_FUNCS(strlcpy fnmatch) + EXTRA_SUPPORT_SYMS= -AC_CHECK_FUNC(strlcpy, [STRLCPY_ST_OBJ= STRLCPY_OBJ=], [STRLCPY_ST_OBJ=strlcpy.o STRLCPY_OBJ='$(OUTPRE)strlcpy.$(OBJEXT)' EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_strlcpy krb5int_strlcat"]) +AC_CHECK_FUNC(strlcpy, +[STRLCPY_ST_OBJ= +STRLCPY_OBJ=], +[STRLCPY_ST_OBJ=strlcpy.o +STRLCPY_OBJ='$(OUTPRE)strlcpy.$(OBJEXT)' +EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS krb5int_strlcpy krb5int_strlcat"]) AC_SUBST(STRLCPY_OBJ) AC_SUBST(STRLCPY_ST_OBJ) + +AC_CHECK_FUNC(fnmatch, +[FNMATCH_ST_OBJ= +FNMATCH_OBJ=], +[FNMATCH_ST_OBJ=fnmatch.o +FNMATCH_OBJ='$(OUTPRE)fnmatch.$(OBJEXT)' +EXTRA_SUPPORT_SYMS="$EXTRA_SUPPORT_SYMS k5_fnmatch"]) +AC_SUBST(FNMATCH_OBJ) +AC_SUBST(FNMATCH_ST_OBJ) + AC_CHECK_FUNC(vasprintf, [PRINTF_ST_OBJ= PRINTF_OBJ=], diff --git a/src/include/k5-platform.h b/src/include/k5-platform.h index 2f24ffaff..e9155cefb 100644 --- a/src/include/k5-platform.h +++ b/src/include/k5-platform.h @@ -35,6 +35,8 @@ * + shared library init/fini hooks * + consistent getpwnam/getpwuid interfaces * + va_copy fudged if not provided + * + strlcpy/strlcat + * + fnmatch * + [v]asprintf * + mkstemp * + zap (support function; macro is in k5-int.h) @@ -54,6 +56,9 @@ #include #include #include +#ifdef HAVE_FNMATCH_H +#include +#endif #ifdef _WIN32 #define CAN_COPY_VA_LIST @@ -927,6 +932,20 @@ extern size_t krb5int_strlcpy(char *dst, const char *src, size_t siz); extern size_t krb5int_strlcat(char *dst, const char *src, size_t siz); #endif +/* Provide fnmatch interface. */ +#ifndef HAVE_FNMATCH +#define fnmatch k5_fnmatch +int k5_fnmatch(const char *pattern, const char *string, int flags); +#define FNM_NOMATCH 1 /* Match failed. */ +#define FNM_NOSYS 2 /* Function not implemented. */ +#define FNM_NORES 3 /* Out of resources */ +#define FNM_NOESCAPE 0x01 /* Disable backslash escaping. */ +#define FNM_PATHNAME 0x02 /* Slash must be matched by slash. */ +#define FNM_PERIOD 0x04 /* Period must be matched by period. */ +#define FNM_CASEFOLD 0x08 /* Pattern is matched case-insensitive */ +#define FNM_LEADING_DIR 0x10 /* Ignore / after Imatch. */ +#endif + /* Provide [v]asprintf interfaces. */ #ifndef HAVE_VSNPRINTF #ifdef _WIN32 diff --git a/src/util/support/Makefile.in b/src/util/support/Makefile.in index 8e4f70f3c..90dc79fb0 100644 --- a/src/util/support/Makefile.in +++ b/src/util/support/Makefile.in @@ -33,6 +33,11 @@ STRLCPY_OBJ=@STRLCPY_OBJ@ ##DOS##STRLCPY_ST_OBJ= strlcpy.o ##DOS##STRLCPY_OBJ= $(OUTPRE)strlcpy.$(OBJEXT) +FNMATCH_ST_OBJ= @FNMATCH_ST_OBJ@ +FNMATCH_OBJ= @FNMATCH_OBJ@ +##DOS##FNMATCH_ST_OBJ= fnmatch.o +##DOS##FNMATCH_OBJ= $(OUTPRE)fnmatch.$(OBJEXT) + PRINTF_ST_OBJ= @PRINTF_ST_OBJ@ PRINTF_OBJ= @PRINTF_OBJ@ ##DOS##PRINTF_ST_OBJ= printf.o @@ -66,6 +71,7 @@ STLIBOBJS= \ path.o \ $(IPC_ST_OBJ) \ $(STRLCPY_ST_OBJ) \ + $(FNMATCH_ST_OBJ) \ $(PRINTF_ST_OBJ) \ $(MKSTEMP_ST_OBJ) @@ -83,6 +89,7 @@ LIBOBJS= \ $(OUTPRE)path.$(OBJEXT) \ $(IPC_OBJ) \ $(STRLCPY_OBJ) \ + $(FNMATCH_OBJ) \ $(PRINTF_OBJ) \ $(MKSTEMP_OBJ) @@ -102,6 +109,7 @@ SRCS=\ $(srcdir)/utf8.c \ $(srcdir)/utf8_conv.c \ $(srcdir)/strlcpy.c \ + $(srcdir)/fnmatch.c \ $(srcdir)/printf.c \ $(srcdir)/mkstemp.c \ $(srcdir)/t_k5buf.c \ diff --git a/src/util/support/deps b/src/util/support/deps index 8dc33bd47..1c81dcdd6 100644 --- a/src/util/support/deps +++ b/src/util/support/deps @@ -35,6 +35,9 @@ utf8_conv.so utf8_conv.po $(OUTPRE)utf8_conv.$(OBJEXT): \ strlcpy.so strlcpy.po $(OUTPRE)strlcpy.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ strlcpy.c +fnmatch.so fnmatch.po $(OUTPRE)fnmatch.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ + $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ + fnmatch.c printf.so printf.po $(OUTPRE)printf.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-thread.h \ printf.c diff --git a/src/util/support/fnmatch.c b/src/util/support/fnmatch.c new file mode 100644 index 000000000..02091e8a5 --- /dev/null +++ b/src/util/support/fnmatch.c @@ -0,0 +1,208 @@ +/* $NetBSD: fnmatch.c,v 1.24 2011/01/31 19:10:18 christos Exp $ */ + +/* + * Copyright (c) 1989, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software contributed to Berkeley by + * Guido van Rossum. + * + * 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. + * 3. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS 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 REGENTS 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. + */ + +#include +#if defined(LIBC_SCCS) && !defined(lint) +#if 0 +static char sccsid[] = "@(#)fnmatch.c 8.2 (Berkeley) 4/16/94"; +#else +__RCSID("$NetBSD: fnmatch.c,v 1.24 2011/01/31 19:10:18 christos Exp $"); +#endif +#endif /* LIBC_SCCS and not lint */ + +/* + * Function fnmatch() as specified in POSIX 1003.2-1992, section B.6. + * Compares a filename or pathname to a pattern. + */ + +#include "k5-platform.h" +#include +#ifndef _DIAGASSERT +#define _DIAGASSERT(x) +#endif + +#define EOS '\0' + +static inline int +foldcase(int ch, int flags) +{ + + if ((flags & FNM_CASEFOLD) != 0 && isupper(ch)) + return tolower(ch); + return ch; +} + +#define FOLDCASE(ch, flags) foldcase((unsigned char)(ch), (flags)) + +static const char * +rangematch(const char *pattern, int test, int flags) +{ + int negate, ok; + char c, c2; + + _DIAGASSERT(pattern != NULL); + + /* + * A bracket expression starting with an unquoted circumflex + * character produces unspecified results (IEEE 1003.2-1992, + * 3.13.2). This implementation treats it like '!', for + * consistency with the regular expression syntax. + * J.T. Conklin (conklin@ngai.kaleida.com) + */ + if ((negate = (*pattern == '!' || *pattern == '^')) != 0) + ++pattern; + + for (ok = 0; (c = FOLDCASE(*pattern++, flags)) != ']';) { + if (c == '\\' && !(flags & FNM_NOESCAPE)) + c = FOLDCASE(*pattern++, flags); + if (c == EOS) + return NULL; + if (*pattern == '-' + && (c2 = FOLDCASE(*(pattern + 1), flags)) != EOS && + c2 != ']') { + pattern += 2; + if (c2 == '\\' && !(flags & FNM_NOESCAPE)) + c2 = FOLDCASE(*pattern++, flags); + if (c2 == EOS) + return NULL; + if (c <= test && test <= c2) + ok = 1; + } else if (c == test) + ok = 1; + } + return ok == negate ? NULL : pattern; +} + + +static int +fnmatchx(const char *pattern, const char *string, int flags, size_t recursion) +{ + const char *stringstart; + char c, test; + + _DIAGASSERT(pattern != NULL); + _DIAGASSERT(string != NULL); + + if (recursion-- == 0) + return FNM_NORES; + + for (stringstart = string;;) { + switch (c = FOLDCASE(*pattern++, flags)) { + case EOS: + if ((flags & FNM_LEADING_DIR) && *string == '/') + return 0; + return *string == EOS ? 0 : FNM_NOMATCH; + case '?': + if (*string == EOS) + return FNM_NOMATCH; + if (*string == '/' && (flags & FNM_PATHNAME)) + return FNM_NOMATCH; + if (*string == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + return FNM_NOMATCH; + ++string; + break; + case '*': + c = FOLDCASE(*pattern, flags); + /* Collapse multiple stars. */ + while (c == '*') + c = FOLDCASE(*++pattern, flags); + + if (*string == '.' && (flags & FNM_PERIOD) && + (string == stringstart || + ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) + return FNM_NOMATCH; + + /* Optimize for pattern with * at end or before /. */ + if (c == EOS) { + if (flags & FNM_PATHNAME) + return (flags & FNM_LEADING_DIR) || + strchr(string, '/') == NULL ? + 0 : FNM_NOMATCH; + else + return 0; + } else if (c == '/' && flags & FNM_PATHNAME) { + if ((string = strchr(string, '/')) == NULL) + return FNM_NOMATCH; + break; + } + + /* General case, use recursion. */ + while ((test = FOLDCASE(*string, flags)) != EOS) { + int e; + switch ((e = fnmatchx(pattern, string, + flags & ~FNM_PERIOD, recursion))) { + case FNM_NOMATCH: + break; + default: + return e; + } + if (test == '/' && flags & FNM_PATHNAME) + break; + ++string; + } + return FNM_NOMATCH; + case '[': + if (*string == EOS) + return FNM_NOMATCH; + if (*string == '/' && flags & FNM_PATHNAME) + return FNM_NOMATCH; + if ((pattern = rangematch(pattern, + FOLDCASE(*string, flags), flags)) == NULL) + return FNM_NOMATCH; + ++string; + break; + case '\\': + if (!(flags & FNM_NOESCAPE)) { + if ((c = FOLDCASE(*pattern++, flags)) == EOS) { + c = '\\'; + --pattern; + } + } + /* FALLTHROUGH */ + default: + if (c != FOLDCASE(*string++, flags)) + return FNM_NOMATCH; + break; + } + } + /* NOTREACHED */ +} + +int +k5_fnmatch(const char *pattern, const char *string, int flags) +{ + return fnmatchx(pattern, string, flags, 64); +}