diff --git a/INSTALL b/INSTALL index a48bfc038..366a12ebf 100644 --- a/INSTALL +++ b/INSTALL @@ -106,6 +106,10 @@ option to configure). For GCC, OpenMP 4.5 is fully supported since GCC 6.1, which is available from http://www.gnu.org/ +If glibc is used, it needs to be of version 2.27 or newer. Older glibc +versions have a longstanding bug where glob() does not return dangling +symlinks as matches, which broadly affects rpmbuild. + Rpm requires a POSIX.1-2008 level operating system. To compile RPM: diff --git a/configure.ac b/configure.ac index 851220606..3a0182d02 100644 --- a/configure.ac +++ b/configure.ac @@ -613,8 +613,6 @@ AC_CHECK_FUNCS( renameat utimensat fchmodat fchownat ], [], [AC_MSG_ERROR([function required by rpm])]) -AC_LIBOBJ(fnmatch) - dnl check if python is requested AC_ARG_ENABLE(python, [AS_HELP_STRING([--enable-python],[build rpm python bindings])], [case "$enable_python" in diff --git a/misc/Makefile.am b/misc/Makefile.am index 3df5f19bb..3a26d4175 100644 --- a/misc/Makefile.am +++ b/misc/Makefile.am @@ -4,7 +4,6 @@ AM_CPPFLAGS = -I$(top_builddir) -I$(top_srcdir) -I$(top_srcdir)/include AM_CPPFLAGS += -I$(top_srcdir)/misc EXTRA_DIST = \ - fnmatch.c fnmatch.h \ stpcpy.c stpncpy.c noinst_LTLIBRARIES = libmisc.la diff --git a/misc/fnmatch.c b/misc/fnmatch.c deleted file mode 100644 index 8de22c8b0..000000000 --- a/misc/fnmatch.c +++ /dev/null @@ -1,613 +0,0 @@ -/* Copyright (C) 1991-1993, 1996-1999, 2000 Free Software Foundation, Inc. - This file is part of the GNU C Library. - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Library General Public License as - published by the Free Software Foundation; either version 2 of the - License, or (at your option) any later version. - - This 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 - Library General Public License for more details. - - You should have received a copy of the GNU Library General Public - License along with this library; see the file COPYING.LIB. If not, - write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, - Boston, MA 02111-1307, USA. */ - -# include "system.h" -# include -# include -# include - -/* Find the first occurrence of C in S or the final NUL byte. */ -static inline char * -__strchrnul (const char *s, int c) -{ - const unsigned char *char_ptr; - const unsigned long int *longword_ptr; - unsigned long int longword, magic_bits, charmask; - - c = (unsigned char) c; - - /* Handle the first few characters by reading one character at a time. - Do this until CHAR_PTR is aligned on a longword boundary. */ - for (char_ptr = (const unsigned char *)s; ((unsigned long int) char_ptr - & (sizeof (longword) - 1)) != 0; - ++char_ptr) - if (*char_ptr == c || *char_ptr == '\0') - return (void *) char_ptr; - - /* All these elucidatory comments refer to 4-byte longwords, - but the theory applies equally well to 8-byte longwords. */ - - longword_ptr = (unsigned long int *) char_ptr; - - /* Bits 31, 24, 16, and 8 of this number are zero. Call these bits - the "holes." Note that there is a hole just to the left of - each byte, with an extra at the end: - - bits: 01111110 11111110 11111110 11111111 - bytes: AAAAAAAA BBBBBBBB CCCCCCCC DDDDDDDD - - The 1-bits make sure that carries propagate to the next 0-bit. - The 0-bits provide holes for carries to fall into. */ - switch (sizeof (longword)) - { - case 4: magic_bits = 0x7efefeffL; break; - case 8: magic_bits = ((0x7efefefeL << 16) << 16) | 0xfefefeffL; break; - default: - abort (); - } - - /* Set up a longword, each of whose bytes is C. */ - charmask = c | (c << 8); - charmask |= charmask << 16; - if (sizeof (longword) > 4) - /* Do the shift in two steps to avoid a warning if long has 32 bits. */ - charmask |= (charmask << 16) << 16; - if (sizeof (longword) > 8) - abort (); - - /* Instead of the traditional loop which tests each character, - we will test a longword at a time. The tricky part is testing - if *any of the four* bytes in the longword in question are zero. */ - for (;;) - { - /* We tentatively exit the loop if adding MAGIC_BITS to - LONGWORD fails to change any of the hole bits of LONGWORD. - - 1) Is this safe? Will it catch all the zero bytes? - Suppose there is a byte with all zeros. Any carry bits - propagating from its left will fall into the hole at its - least significant bit and stop. Since there will be no - carry from its most significant bit, the LSB of the - byte to the left will be unchanged, and the zero will be - detected. - - 2) Is this worthwhile? Will it ignore everything except - zero bytes? Suppose every byte of LONGWORD has a bit set - somewhere. There will be a carry into bit 8. If bit 8 - is set, this will carry into bit 16. If bit 8 is clear, - one of bits 9-15 must be set, so there will be a carry - into bit 16. Similarly, there will be a carry into bit - 24. If one of bits 24-30 is set, there will be a carry - into bit 31, so all of the hole bits will be changed. - - The one misfire occurs when bits 24-30 are clear and bit - 31 is set; in this case, the hole at bit 31 is not - changed. If we had access to the processor carry flag, - we could close this loophole by putting the fourth hole - at bit 32! - - So it ignores everything except 128's, when they're aligned - properly. - - 3) But wait! Aren't we looking for C as well as zero? - Good point. So what we do is XOR LONGWORD with a longword, - each of whose bytes is C. This turns each byte that is C - into a zero. */ - - longword = *longword_ptr++; - - /* Add MAGIC_BITS to LONGWORD. */ - if ((((longword + magic_bits) - - /* Set those bits that were unchanged by the addition. */ - ^ ~longword) - - /* Look at only the hole bits. If any of the hole bits - are unchanged, most likely one of the bytes was a - zero. */ - & ~magic_bits) != 0 || - - /* That caught zeroes. Now test for C. */ - ((((longword ^ charmask) + magic_bits) ^ ~(longword ^ charmask)) - & ~magic_bits) != 0) - { - /* Which of the bytes was C or zero? - If none of them were, it was a misfire; continue the search. */ - - const unsigned char *cp = (const unsigned char *) (longword_ptr - 1); - - if (*cp == c || *cp == '\0') - return (char *) cp; - if (*++cp == c || *cp == '\0') - return (char *) cp; - if (*++cp == c || *cp == '\0') - return (char *) cp; - if (*++cp == c || *cp == '\0') - return (char *) cp; - if (sizeof (longword) > 4) - { - if (*++cp == c || *cp == '\0') - return (char *) cp; - if (*++cp == c || *cp == '\0') - return (char *) cp; - if (*++cp == c || *cp == '\0') - return (char *) cp; - if (*++cp == c || *cp == '\0') - return (char *) cp; - } - } - } - - /* This should never happen. */ - return NULL; -} - -/* For platform which support the ISO C amendement 1 functionality we - support user defined character classes. */ -#if defined _LIBC || (defined HAVE_WCTYPE_H && defined HAVE_WCHAR_H) -/* Solaris 2.5 has a bug: must be included before . */ -# include -# include -#endif - -/* 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 -# 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 - -/* Avoid depending on library functions or files - whose names are inconsistent. */ - -# if !defined _LIBC && !defined getenv -extern char *getenv (); -# endif - -# ifndef errno -extern int errno; -# endif - -/* Match STRING against the filename pattern PATTERN, returning zero if - it matches, nonzero if not. */ -static int -#ifdef _LIBC -internal_function -#endif -internal_fnmatch (const char *pattern, const char *string, - int no_leading_period, int flags) -{ - register const char *p = pattern, *n = string; - register unsigned char c; - -/* 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 - - while ((c = *p++) != '\0') - { - c = FOLD (c); - - switch (c) - { - case '?': - if (*n == '\0') - return FNM_NOMATCH; - else if (*n == '/' && (flags & FNM_FILE_NAME)) - return FNM_NOMATCH; - else if (*n == '.' && no_leading_period - && (n == string - || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) - return FNM_NOMATCH; - break; - - case '\\': - if (!(flags & FNM_NOESCAPE)) - { - c = *p++; - if (c == '\0') - /* Trailing \ loses. */ - return FNM_NOMATCH; - c = FOLD (c); - } - if (FOLD ((unsigned char) *n) != c) - return FNM_NOMATCH; - break; - - case '*': - if (*n == '.' && no_leading_period - && (n == string - || (n[-1] == '/' && (flags & FNM_FILE_NAME)))) - return FNM_NOMATCH; - - for (c = *p++; c == '?' || c == '*'; c = *p++) - { - if (*n == '/' && (flags & FNM_FILE_NAME)) - /* A slash does not match a wildcard under FNM_FILE_NAME. */ - return FNM_NOMATCH; - else if (c == '?') - { - /* A ? needs to match one character. */ - if (*n == '\0') - /* There isn't another character; no match. */ - 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 does mean it cannot match. If the FNM_LEADING_DIR - flag is set and exactly one slash is following, we have - a match. */ - { - int result = (flags & FNM_FILE_NAME) == 0 ? 0 : FNM_NOMATCH; - - if (flags & FNM_FILE_NAME) - { - const char *slashp = strchr (n, '/'); - - if (flags & FNM_LEADING_DIR) - { - if (slashp != NULL - && strchr (slashp + 1, '/') == NULL) - result = 0; - } - else - { - if (slashp == NULL) - result = 0; - } - } - - return result; - } - else - { - const char *endp; - - endp = __strchrnul (n, (flags & FNM_FILE_NAME) ? '/' : '\0'); - - if (c == '[') - { - int flags2 = ((flags & FNM_FILE_NAME) - ? flags : (flags & ~FNM_PERIOD)); - - for (--p; n < endp; ++n) - if (internal_fnmatch (p, n, - (no_leading_period - && (n == string - || (n[-1] == '/' - && (flags - & FNM_FILE_NAME)))), - flags2) - == 0) - return 0; - } - else if (c == '/' && (flags & FNM_FILE_NAME)) - { - while (*n != '\0' && *n != '/') - ++n; - if (*n == '/' - && (internal_fnmatch (p, n + 1, flags & FNM_PERIOD, - flags) == 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) - if (FOLD ((unsigned char) *n) == c - && (internal_fnmatch (p, n, - (no_leading_period - && (n == string - || (n[-1] == '/' - && (flags - & FNM_FILE_NAME)))), - flags2) == 0)) - return 0; - } - } - - /* 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. */ - static int posixly_correct; - register int not; - char cold; - - if (posixly_correct == 0) - posixly_correct = getenv ("POSIXLY_CORRECT") != NULL ? 1 : -1; - - if (*n == '\0') - return FNM_NOMATCH; - - if (*n == '.' && no_leading_period && (n == string - || (n[-1] == '/' - && (flags - & FNM_FILE_NAME)))) - return FNM_NOMATCH; - - if (*n == '/' && (flags & FNM_FILE_NAME)) - /* `/' cannot be matched. */ - return FNM_NOMATCH; - - not = (*p == '!' || (posixly_correct < 0 && *p == '^')); - if (not) - ++p; - - c = *p++; - for (;;) - { - unsigned char fn = FOLD ((unsigned char) *n); - - if (!(flags & FNM_NOESCAPE) && c == '\\') - { - if (*p == '\0') - return FNM_NOMATCH; - c = FOLD ((unsigned char) *p); - ++p; - - if (c == fn) - goto matched; - } - else if (c == '[' && *p == ':') - { - /* 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 == ':' && p[1] == ']') - { - p += 2; - break; - } - if (c < 'a' || c >= 'z') - { - /* This cannot possibly be a character class name. - Match it as a normal range. */ - p = startp; - c = '['; - goto normal_bracket; - } - str[c1++] = c; - } - str[c1] = '\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 (__iswctype (__btowc ((unsigned char) *n), wt)) - goto matched; -# else - if ((STREQ (str, "alnum") && ISALNUM ((unsigned char) *n)) - || (STREQ (str, "alpha") && ISALPHA ((unsigned char) *n)) - || (STREQ (str, "blank") && ISBLANK ((unsigned char) *n)) - || (STREQ (str, "cntrl") && ISCNTRL ((unsigned char) *n)) - || (STREQ (str, "digit") && ISDIGIT ((unsigned char) *n)) - || (STREQ (str, "graph") && ISGRAPH ((unsigned char) *n)) - || (STREQ (str, "lower") && ISLOWER ((unsigned char) *n)) - || (STREQ (str, "print") && ISPRINT ((unsigned char) *n)) - || (STREQ (str, "punct") && ISPUNCT ((unsigned char) *n)) - || (STREQ (str, "space") && ISSPACE ((unsigned char) *n)) - || (STREQ (str, "upper") && ISUPPER ((unsigned char) *n)) - || (STREQ (str, "xdigit") && ISXDIGIT ((unsigned char) *n))) - goto matched; -# endif - } - else if (c == '\0') - /* [ (unterminated) loses. */ - return FNM_NOMATCH; - else - { - c = FOLD (c); - normal_bracket: - if (c == fn) - goto matched; - - cold = c; - c = *p++; - - if (c == '-' && *p != ']') - { - /* It is a range. */ - char lo[2]; - char fc[2]; - unsigned char cend = *p++; - if (!(flags & FNM_NOESCAPE) && cend == '\\') - cend = *p++; - if (cend == '\0') - return FNM_NOMATCH; - - lo[0] = cold; - lo[1] = '\0'; - fc[0] = fn; - fc[1] = '\0'; - if (strcoll (lo, fc) <= 0) - { - char hi[2]; - hi[0] = FOLD (cend); - hi[1] = '\0'; - if (strcoll (fc, hi) <= 0) - goto matched; - } - - c = *p++; - } - } - - if (c == ']') - break; - } - - if (!not) - return FNM_NOMATCH; - break; - - matched: - /* Skip the rest of the [...] that already matched. */ - while (c != ']') - { - if (c == '\0') - /* [... (unterminated) loses. */ - return FNM_NOMATCH; - - c = *p++; - if (!(flags & FNM_NOESCAPE) && c == '\\') - { - if (*p == '\0') - return FNM_NOMATCH; - /* XXX 1003.2d11 is unclear if this is right. */ - ++p; - } - else if (c == '[' && *p == ':') - { - do - if (*++p == '\0') - return FNM_NOMATCH; - while (*p != ':' || p[1] == ']'); - p += 2; - c = *p; - } - } - if (not) - return FNM_NOMATCH; - } - break; - - default: - if (c != FOLD ((unsigned char) *n)) - return FNM_NOMATCH; - } - - ++n; - } - - if (*n == '\0') - return 0; - - if ((flags & FNM_LEADING_DIR) && *n == '/') - /* The FNM_LEADING_DIR flag says that "foo*" matches "foobar/frobozz". */ - return 0; - - return FNM_NOMATCH; - -# undef FOLD -} - - -int -fnmatch (const char *pattern, const char *string, int flags) -{ - return internal_fnmatch (pattern, string, flags & FNM_PERIOD, flags); -} - -#endif /* _LIBC or not __GNU_LIBRARY__. */ diff --git a/misc/fnmatch.h b/misc/fnmatch.h deleted file mode 100644 index c0fd6a920..000000000 --- a/misc/fnmatch.h +++ /dev/null @@ -1,85 +0,0 @@ -/* Copyright (C) 1991,92,93,96,97,98,99,2001 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, write to the Free - Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA - 02111-1307 USA. */ - -#ifndef _FNMATCH_H -#define _FNMATCH_H 1 - -#ifdef __cplusplus -extern "C" { -#endif - -#if defined __cplusplus || (defined __STDC__ && __STDC__) || defined WINDOWS32 -# if !defined __GLIBC__ || !defined __P -# undef __P -# define __P(protos) protos -# endif -#else /* Not C++ or ANSI C. */ -# undef __P -# define __P(protos) () -/* We can get away without defining `const' here only because in this file - it is used only inside the prototype for `fnmatch', which is elided in - non-ANSI C where `const' is problematical. */ -#endif /* C++ or ANSI C. */ - -#ifndef const -# if (defined __STDC__ && __STDC__) || defined __cplusplus -# define __const const -# else -# define __const -# endif -#endif - -/* We #undef these before defining them because some losing systems - (HP-UX A.08.07 for example) define these in . */ -#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 fnmatch __P ((__const char *__pattern, __const char *__name, - int __flags)); - -#ifdef __cplusplus -} -#endif - -#endif /* fnmatch.h */ diff --git a/rpmio/rpmglob.c b/rpmio/rpmglob.c index 93f7fa54d..7dbc34185 100644 --- a/rpmio/rpmglob.c +++ b/rpmio/rpmglob.c @@ -17,11 +17,6 @@ write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -/* AIX requires this to be the first thing in the file. */ -#if defined _AIX && !defined __GNUC__ -#pragma alloca -#endif - #include "system.h" #include @@ -30,56 +25,8 @@ #include #include #include /* S_ISDIR */ - -/* Bits set in the FLAGS argument to `glob'. */ -#define GLOB_ERR (1 << 0) /* Return on read errors. */ -#define GLOB_MARK (1 << 1) /* Append a slash to each name. */ -#define GLOB_NOSORT (1 << 2) /* Don't sort the names. */ -#define GLOB_DOOFFS (1 << 3) /* Insert PGLOB->gl_offs NULLs. */ -#define GLOB_NOCHECK (1 << 4) /* If nothing matches, return the pattern. */ -#define GLOB_APPEND (1 << 5) /* Append to results of a previous call. */ -#define GLOB_NOESCAPE (1 << 6) /* Backslashes don't quote metacharacters. */ -#define GLOB_PERIOD (1 << 7) /* Leading `.' can be matched by metachars. */ - -#define GLOB_MAGCHAR (1 << 8) /* Set in gl_flags if any metachars seen. */ -#define GLOB_ALTDIRFUNC (1 << 9) /* Use gl_opendir et al functions. */ -#define GLOB_BRACE (1 << 10) /* Expand "{a,b}" to "a" "b". */ -#define GLOB_NOMAGIC (1 << 11) /* If no magic chars, return the pattern. */ -#define GLOB_TILDE (1 << 12) /* Expand ~user and ~ to home directories. */ -#define GLOB_ONLYDIR (1 << 13) /* Match only directories. */ -#define GLOB_TILDE_CHECK (1 << 14) /* Like GLOB_TILDE but return an error - if the user name is not available. */ -#define __GLOB_FLAGS (GLOB_ERR|GLOB_MARK|GLOB_NOSORT|GLOB_DOOFFS| \ - GLOB_NOESCAPE|GLOB_NOCHECK|GLOB_APPEND| \ - GLOB_PERIOD|GLOB_ALTDIRFUNC|GLOB_BRACE| \ - GLOB_NOMAGIC|GLOB_TILDE|GLOB_ONLYDIR|GLOB_TILDE_CHECK) - -/* Error returns from `glob'. */ -#define GLOB_NOSPACE 1 /* Ran out of memory. */ -#define GLOB_ABORTED 2 /* Read error. */ -#define GLOB_NOMATCH 3 /* No matches found. */ -#define GLOB_NOSYS 4 /* Not implemented. */ - -/* Structure describing a globbing run. */ -typedef struct { - size_t gl_pathc; /* Count of paths matched by the pattern. */ - char **gl_pathv; /* List of matched pathnames. */ - size_t gl_offs; /* Slots to reserve in `gl_pathv'. */ - int gl_flags; /* Set to FLAGS, maybe | GLOB_MAGCHAR. */ - - /* If the GLOB_ALTDIRFUNC flag is set, the following functions - are used instead of the normal file access functions. */ - void (*gl_closedir)(void *); - struct dirent *(*gl_readdir)(void *); - void *(*gl_opendir)(const char *); - int (*gl_lstat)(const char *, struct stat *); - int (*gl_stat)(const char *, struct stat *); -} glob_t; - -#include -#ifndef __set_errno -#define __set_errno(val) errno = (val) -#endif +#include +#include #include #include @@ -87,27 +34,6 @@ typedef struct { #include "debug.h" -/* Outcomment the following line for production quality code. */ -/* #define NDEBUG 1 */ - -#define GLOB_INTERFACE_VERSION 1 - -static void globfree(glob_t * pglob); -static inline const char *next_brace_sub(const char *begin); -static int glob_in_dir(const char *pattern, const char *directory, - int flags, - int (*errfunc) (const char *, int), - glob_t * pglob); -static int prefix_array(const char *prefix, char **array, size_t n); -static int collated_compare(const void *, const void *); - -#ifndef HAVE_MEMPCPY -static void * mempcpy(void *dest, const void *src, size_t n) -{ - return (char *) memcpy(dest, src, n) + n; -} -#endif - /* Find the end of the sub-pattern in a brace expression. We define this as an inline function if the compiler permits. */ static inline const char *next_brace_sub(const char *begin) @@ -126,500 +52,6 @@ static inline const char *next_brace_sub(const char *begin) return *cp != '\0' ? cp : NULL; } -static int __glob_pattern_p(const char *pattern, int quote); - -/* Do glob searching for PATTERN, placing results in PGLOB. - The bits defined above may be set in FLAGS. - If a directory cannot be opened or read and ERRFUNC is not nil, - it is called with the pathname that caused the error, and the - `errno' value from the failing call; if it returns non-zero - `glob' returns GLOB_ABORTED; if it returns zero, the error is ignored. - If memory cannot be allocated for PGLOB, GLOB_NOSPACE is returned. - Otherwise, `glob' returns zero. */ -static int -glob(const char *pattern, int flags, - int (*errfunc)(const char *, int), glob_t * pglob) -{ - const char *filename; - const char *dirname; - size_t dirlen; - int status; - int oldcount; - - if (pattern == NULL || pglob == NULL || (flags & ~__GLOB_FLAGS) != 0) { - __set_errno(EINVAL); - return -1; - } - - if (flags & GLOB_BRACE) { - const char *begin = strchr(pattern, '{'); - if (begin != NULL) { - /* Allocate working buffer large enough for our work. Note that - we have at least an opening and closing brace. */ - int firstc; - char *alt_start; - const char *p; - const char *next; - const char *rest; - size_t rest_len; - char onealt[strlen(pattern) - 1]; - - /* We know the prefix for all sub-patterns. */ - alt_start = mempcpy(onealt, pattern, begin - pattern); - - /* Find the first sub-pattern and at the same time find the - rest after the closing brace. */ - next = next_brace_sub(begin + 1); - if (next == NULL) { - /* It is an illegal expression. */ - return glob(pattern, flags & ~GLOB_BRACE, errfunc, pglob); - } - - /* Now find the end of the whole brace expression. */ - rest = next; - while (*rest != '}') { - rest = next_brace_sub(rest + 1); - if (rest == NULL) { - /* It is an illegal expression. */ - return glob(pattern, flags & ~GLOB_BRACE, errfunc, - pglob); - } - } - /* Please note that we now can be sure the brace expression - is well-formed. */ - rest_len = strlen(++rest) + 1; - - /* We have a brace expression. BEGIN points to the opening {, - NEXT points past the terminator of the first element, and END - points past the final }. We will accumulate result names from - recursive runs for each brace alternative in the buffer using - GLOB_APPEND. */ - - if (!(flags & GLOB_APPEND)) { - /* This call is to set a new vector, so clear out the - vector so we can append to it. */ - pglob->gl_pathc = 0; - pglob->gl_pathv = NULL; - } - firstc = pglob->gl_pathc; - - p = begin + 1; - while (1) { - int result; - - /* Construct the new glob expression. */ - mempcpy(mempcpy(alt_start, p, next - p), rest, rest_len); - - result = glob(onealt, - ((flags & ~(GLOB_NOCHECK | GLOB_NOMAGIC)) - | GLOB_APPEND), errfunc, pglob); - - /* If we got an error, return it. */ - if (result && result != GLOB_NOMATCH) { - if (!(flags & GLOB_APPEND)) - globfree(pglob); - return result; - } - - if (*next == '}') - /* We saw the last entry. */ - break; - - p = next + 1; - next = next_brace_sub(p); - assert(next != NULL); - } - - if (pglob->gl_pathc != firstc) - /* We found some entries. */ - return 0; - else if (!(flags & (GLOB_NOCHECK | GLOB_NOMAGIC))) - return GLOB_NOMATCH; - } - } - - /* Find the filename. */ - filename = strrchr(pattern, '/'); - if (filename == NULL) { - /* This can mean two things: a simple name or "~name". The latter - case is nothing but a notation for a directory. */ - if ((flags & (GLOB_TILDE | GLOB_TILDE_CHECK)) && pattern[0] == '~') { - dirname = pattern; - dirlen = strlen(pattern); - - /* Set FILENAME to NULL as a special flag. This is ugly but - other solutions would require much more code. We test for - this special case below. */ - filename = NULL; - } else { - filename = pattern; - dirname = "."; - dirlen = 0; - } - } else if (filename == pattern) { - /* "/pattern". */ - dirname = "/"; - dirlen = 1; - ++filename; - } else { - char *newp; - dirlen = filename - pattern; - newp = (char *) alloca(dirlen + 1); - *((char *) mempcpy(newp, pattern, dirlen)) = '\0'; - dirname = newp; - ++filename; - - if (filename[0] == '\0' && dirlen > 1) { - /* "pattern/". Expand "pattern", appending slashes. */ - int val = glob(dirname, flags | GLOB_MARK, errfunc, pglob); - if (val == 0) - pglob->gl_flags = ((pglob->gl_flags & ~GLOB_MARK) - | (flags & GLOB_MARK)); - return val; - } - } - - if (!(flags & GLOB_APPEND)) { - pglob->gl_pathc = 0; - pglob->gl_pathv = NULL; - } - - oldcount = pglob->gl_pathc; - - if ((flags & (GLOB_TILDE | GLOB_TILDE_CHECK)) && dirname[0] == '~') { - if (dirname[1] == '\0' || dirname[1] == '/') { - /* Look up home directory. */ - const char *home_dir = getenv("HOME"); - if (home_dir == NULL || home_dir[0] == '\0') { - int success; - char *name; - success = (name = getlogin()) != NULL; - if (success) { - struct passwd *p; - p = getpwnam(name); - if (p != NULL) - home_dir = p->pw_dir; - } - } - if (home_dir == NULL || home_dir[0] == '\0') { - if (flags & GLOB_TILDE_CHECK) - return GLOB_NOMATCH; - else - home_dir = "~"; /* No luck. */ - } - /* Now construct the full directory. */ - if (dirname[1] == '\0') - dirname = home_dir; - else { - char *newp; - size_t home_len = strlen(home_dir); - newp = (char *) alloca(home_len + dirlen + 1); - mempcpy(mempcpy(newp, home_dir, home_len), - &dirname[1], dirlen); - dirname = newp; - } - } - else { - char *end_name = strchr(dirname, '/'); - const char *user_name; - const char *home_dir; - - if (end_name == NULL) - user_name = dirname + 1; - else { - char *newp; - newp = (char *) alloca(end_name - dirname + 1); - *((char *) mempcpy(newp, dirname + 1, end_name - dirname)) - = '\0'; - user_name = newp; - } - - /* Look up specific user's home directory. */ - { - struct passwd *p; - p = getpwnam(user_name); - if (p != NULL) - home_dir = p->pw_dir; - else - home_dir = NULL; - } - /* If we found a home directory use this. */ - if (home_dir != NULL) { - char *newp; - size_t home_len = strlen(home_dir); - size_t rest_len = end_name == NULL ? 0 : strlen(end_name); - newp = (char *) alloca(home_len + rest_len + 1); - *((char *) mempcpy(mempcpy(newp, home_dir, home_len), - end_name, rest_len)) = '\0'; - dirname = newp; - } else if (flags & GLOB_TILDE_CHECK) - /* We have to regard it as an error if we cannot find the - home directory. */ - return GLOB_NOMATCH; - } - } - - /* Now test whether we looked for "~" or "~NAME". In this case we - can give the answer now. */ - if (filename == NULL) { - struct stat st; - - /* Return the directory if we don't check for error or if it exists. */ - if ((flags & GLOB_NOCHECK) - || (((flags & GLOB_ALTDIRFUNC) - ? (*pglob->gl_stat) (dirname, &st) - : stat(dirname, &st)) == 0 && S_ISDIR(st.st_mode))) { - pglob->gl_pathv - = (char **) xrealloc(pglob->gl_pathv, - (pglob->gl_pathc + - ((flags & GLOB_DOOFFS) ? - pglob->gl_offs : 0) + - 1 + 1) * sizeof(char *)); - - if (flags & GLOB_DOOFFS) - while (pglob->gl_pathc < pglob->gl_offs) - pglob->gl_pathv[pglob->gl_pathc++] = NULL; - - pglob->gl_pathv[pglob->gl_pathc] = xstrdup(dirname); - if (pglob->gl_pathv[pglob->gl_pathc] == NULL) { - free(pglob->gl_pathv); - return GLOB_NOSPACE; - } - pglob->gl_pathv[++pglob->gl_pathc] = NULL; - pglob->gl_flags = flags; - - return 0; - } - - /* Not found. */ - return GLOB_NOMATCH; - } - - if (__glob_pattern_p(dirname, !(flags & GLOB_NOESCAPE))) { - /* The directory name contains metacharacters, so we - have to glob for the directory, and then glob for - the pattern in each directory found. */ - glob_t dirs; - register int i; - - if ((flags & GLOB_ALTDIRFUNC) != 0) { - /* Use the alternative access functions also in the recursive - call. */ - dirs.gl_opendir = pglob->gl_opendir; - dirs.gl_readdir = pglob->gl_readdir; - dirs.gl_closedir = pglob->gl_closedir; - dirs.gl_stat = pglob->gl_stat; - dirs.gl_lstat = pglob->gl_lstat; - } - - status = glob(dirname, - ((flags & (GLOB_ERR | GLOB_NOCHECK | GLOB_NOESCAPE - | GLOB_ALTDIRFUNC)) - | GLOB_NOSORT | GLOB_ONLYDIR), errfunc, &dirs); - if (status != 0) - return status; - - /* We have successfully globbed the preceding directory name. - For each name we found, call glob_in_dir on it and FILENAME, - appending the results to PGLOB. */ - for (i = 0; i < dirs.gl_pathc; ++i) { - int old_pathc = pglob->gl_pathc; - status = glob_in_dir(filename, dirs.gl_pathv[i], - ((flags | GLOB_APPEND) - & ~(GLOB_NOCHECK | GLOB_ERR)), - errfunc, pglob); - if (status == GLOB_NOMATCH) - /* No matches in this directory. Try the next. */ - continue; - - if (status != 0) { - globfree(&dirs); - globfree(pglob); - return status; - } - - /* Stick the directory on the front of each name. */ - if (prefix_array(dirs.gl_pathv[i], - &pglob->gl_pathv[old_pathc], - pglob->gl_pathc - old_pathc)) { - globfree(&dirs); - globfree(pglob); - return GLOB_NOSPACE; - } - } - - flags |= GLOB_MAGCHAR; - - /* We have ignored the GLOB_NOCHECK flag in the `glob_in_dir' calls. - But if we have not found any matching entry and thie GLOB_NOCHECK - flag was set we must return the list consisting of the disrectory - names followed by the filename. */ - if (pglob->gl_pathc == oldcount) { - /* No matches. */ - if (flags & GLOB_NOCHECK) { - size_t filename_len = strlen(filename) + 1; - char **new_pathv; - struct stat st; - - /* This is an pessimistic guess about the size. */ - pglob->gl_pathv - = (char **) xrealloc(pglob->gl_pathv, - (pglob->gl_pathc + - ((flags & GLOB_DOOFFS) ? - pglob->gl_offs : 0) + - dirs.gl_pathc + 1) * - sizeof(char *)); - - if (flags & GLOB_DOOFFS) - while (pglob->gl_pathc < pglob->gl_offs) - pglob->gl_pathv[pglob->gl_pathc++] = NULL; - - for (i = 0; i < dirs.gl_pathc; ++i) { - const char *dir = dirs.gl_pathv[i]; - size_t dir_len = strlen(dir); - - /* First check whether this really is a directory. */ - if (((flags & GLOB_ALTDIRFUNC) - ? (*pglob->gl_stat) (dir, &st) : stat(dir, - &st)) != 0 - || !S_ISDIR(st.st_mode)) - /* No directory, ignore this entry. */ - continue; - - pglob->gl_pathv[pglob->gl_pathc] = xmalloc(dir_len + 1 - + - filename_len); - mempcpy(mempcpy - (mempcpy - (pglob->gl_pathv[pglob->gl_pathc], dir, - dir_len), "/", 1), filename, filename_len); - ++pglob->gl_pathc; - } - - pglob->gl_pathv[pglob->gl_pathc] = NULL; - pglob->gl_flags = flags; - - /* Now we know how large the gl_pathv vector must be. */ - new_pathv = (char **) xrealloc(pglob->gl_pathv, - ((pglob->gl_pathc + 1) - * sizeof(char *))); - pglob->gl_pathv = new_pathv; - } else - return GLOB_NOMATCH; - } - - globfree(&dirs); - } else { - status = glob_in_dir(filename, dirname, flags, errfunc, pglob); - if (status != 0) - return status; - - if (dirlen > 0) { - /* Stick the directory on the front of each name. */ - int ignore = oldcount; - - if ((flags & GLOB_DOOFFS) && ignore < pglob->gl_offs) - ignore = pglob->gl_offs; - - if (prefix_array(dirname, - &pglob->gl_pathv[ignore], - pglob->gl_pathc - ignore)) { - globfree(pglob); - return GLOB_NOSPACE; - } - } - } - - if (flags & GLOB_MARK) { - /* Append slashes to directory names. */ - int i; - struct stat st; - for (i = oldcount; i < pglob->gl_pathc; ++i) - if (((flags & GLOB_ALTDIRFUNC) - ? (*pglob->gl_stat) (pglob->gl_pathv[i], &st) - : stat(pglob->gl_pathv[i], &st)) == 0 - && S_ISDIR(st.st_mode)) { - size_t len = strlen(pglob->gl_pathv[i]) + 2; - char *new = xrealloc(pglob->gl_pathv[i], len); - strcpy(&new[len - 2], "/"); - pglob->gl_pathv[i] = new; - } - } - - if (!(flags & GLOB_NOSORT)) { - /* Sort the vector. */ - int non_sort = oldcount; - - if ((flags & GLOB_DOOFFS) && pglob->gl_offs > oldcount) - non_sort = pglob->gl_offs; - - qsort(& pglob->gl_pathv[non_sort], - pglob->gl_pathc - non_sort, - sizeof(char *), collated_compare); - } - - return 0; -} - - -/* Free storage allocated in PGLOB by a previous `glob' call. */ -static void globfree(glob_t * pglob) -{ - if (pglob->gl_pathv != NULL) { - register int i; - for (i = 0; i < pglob->gl_pathc; ++i) - if (pglob->gl_pathv[i] != NULL) - free(pglob->gl_pathv[i]); - free(pglob->gl_pathv); - } -} - - -/* Do a collated comparison of A and B. */ -static int collated_compare(const void * a, const void * b) -{ - const char *const s1 = *(const char *const *const) a; - const char *const s2 = *(const char *const *const) b; - - if (s1 == s2) - return 0; - if (s1 == NULL) - return 1; - if (s2 == NULL) - return -1; - return strcoll(s1, s2); -} - - -/* Prepend DIRNAME to each of N members of ARRAY, replacing ARRAY's - elements in place. Return nonzero if out of memory, zero if successful. - A slash is inserted between DIRNAME and each elt of ARRAY, - unless DIRNAME is just "/". Each old element of ARRAY is freed. */ -static int prefix_array(const char *dirname, char **array, size_t n) -{ - register size_t i; - size_t dirlen = strlen(dirname); - - if (dirlen == 1 && dirname[0] == '/') - /* DIRNAME is just "/", so normal prepending would get us "//foo". - We want "/foo" instead, so don't prepend any chars from DIRNAME. */ - dirlen = 0; - - for (i = 0; i < n; ++i) { - size_t eltlen = strlen(array[i]) + 1; - char *new = (char *) xmalloc(dirlen + 1 + eltlen); - { - char *endp = (char *) mempcpy(new, dirname, dirlen); - *endp++ = '/'; - mempcpy(endp, array[i], eltlen); - } - free(array[i]); - array[i] = new; - } - - return 0; -} - /* Return nonzero if PATTERN contains any metacharacters. Metacharacters can be quoted with backslashes if QUOTE is nonzero. */ static int __glob_pattern_p(const char *pattern, int quote) @@ -651,153 +83,6 @@ static int __glob_pattern_p(const char *pattern, int quote) return 0; } -/* Like `glob', but PATTERN is a final pathname component, - and matches are searched for in DIRECTORY. - The GLOB_NOSORT bit in FLAGS is ignored. No sorting is ever done. - The GLOB_APPEND flag is assumed to be set (always appends). */ -static int -glob_in_dir(const char *pattern, const char *directory, int flags, - int (*errfunc)(const char *, int), glob_t * pglob) -{ - void * stream = NULL; - - struct globlink { - struct globlink *next; - char *name; - }; - struct globlink *names = NULL; - size_t nfound; - int meta; - int save; - - meta = __glob_pattern_p(pattern, !(flags & GLOB_NOESCAPE)); - if (meta == 0) { - if (flags & (GLOB_NOCHECK | GLOB_NOMAGIC)) - /* We need not do any tests. The PATTERN contains no meta - characters and we must not return an error therefore the - result will always contain exactly one name. */ - flags |= GLOB_NOCHECK; - else { - /* Since we use the normal file functions we can also use stat() - to verify the file is there. */ - struct stat st; - size_t patlen = strlen(pattern); - size_t dirlen = strlen(directory); - char *fullname = (char *) alloca(dirlen + 1 + patlen + 1); - - mempcpy(mempcpy(mempcpy(fullname, directory, dirlen), - "/", 1), pattern, patlen + 1); - if (((flags & GLOB_ALTDIRFUNC) - ? (*pglob->gl_stat) (fullname, &st) - : stat(fullname, &st)) == 0) - /* We found this file to be existing. Now tell the rest - of the function to copy this name into the result. */ - flags |= GLOB_NOCHECK; - } - - nfound = 0; - } else { - if (pattern[0] == '\0') { - /* This is a special case for matching directories like in - "*a/". */ - names = (struct globlink *) alloca(sizeof(struct globlink)); - names->name = (char *) xmalloc(1); - names->name[0] = '\0'; - names->next = NULL; - nfound = 1; - meta = 0; - } else { - stream = ((flags & GLOB_ALTDIRFUNC) - ? (*pglob->gl_opendir) (directory) - : opendir(directory)); - if (stream == NULL) { - if (errno != ENOTDIR - && ((errfunc != NULL && (*errfunc) (directory, errno)) - || (flags & GLOB_ERR))) - return GLOB_ABORTED; - nfound = 0; - meta = 0; - } else { - int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0) | - ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0)); - nfound = 0; - flags |= GLOB_MAGCHAR; - - while (1) { - const char *name; - size_t len; - struct dirent *d = ((flags & GLOB_ALTDIRFUNC) - ? (*pglob->gl_readdir) (stream) - : readdir((DIR *) stream)); - if (d == NULL) - break; - -#ifdef HAVE_STRUCT_DIRENT_D_TYPE - /* If we shall match only directories use the information - provided by the dirent call if possible. */ - if ((flags & GLOB_ONLYDIR) - && d->d_type != DT_UNKNOWN && d->d_type != DT_DIR) - continue; -#endif - - name = d->d_name; - - if (fnmatch(pattern, name, fnm_flags) == 0) { - struct globlink *new = (struct globlink *) - alloca(sizeof(struct globlink)); - len = strlen(d->d_name); - new->name = (char *) xmalloc(len + 1); - *((char *) mempcpy(new->name, name, len)) - = '\0'; - new->next = names; - names = new; - ++nfound; - } - } - } - } - } - - if (nfound == 0 && (flags & GLOB_NOCHECK)) { - size_t len = strlen(pattern); - nfound = 1; - names = (struct globlink *) alloca(sizeof(struct globlink)); - names->next = NULL; - names->name = (char *) xmalloc(len + 1); - *((char *) mempcpy(names->name, pattern, len)) = '\0'; - } - - if (nfound != 0) { - pglob->gl_pathv - = (char **) xrealloc(pglob->gl_pathv, - (pglob->gl_pathc + - ((flags & GLOB_DOOFFS) ? pglob-> - gl_offs : 0) + nfound + - 1) * sizeof(char *)); - - if (flags & GLOB_DOOFFS) - while (pglob->gl_pathc < pglob->gl_offs) - pglob->gl_pathv[pglob->gl_pathc++] = NULL; - - for (; names != NULL; names = names->next) - pglob->gl_pathv[pglob->gl_pathc++] = names->name; - pglob->gl_pathv[pglob->gl_pathc] = NULL; - - pglob->gl_flags = flags; - } - - save = errno; - if (stream != NULL) { - if (flags & GLOB_ALTDIRFUNC) - (*pglob->gl_closedir) (stream); - else - closedir((DIR *) stream); - } - __set_errno(save); - - return nfound == 0 ? GLOB_NOMATCH : 0; -} - /* librpmio exported interfaces */ int rpmGlob(const char * patterns, int * argcPtr, ARGV_t * argvPtr) diff --git a/system.h b/system.h index a5d236843..461712a0a 100644 --- a/system.h +++ b/system.h @@ -100,8 +100,4 @@ extern int fdatasync(int fildes); #define N_(Text) Text -/* ============== from misc/miscfn.h */ - -#include "misc/fnmatch.h" - #endif /* H_SYSTEM */