From 097923f7b19a1f40313ecce0e743e42df5c75673 Mon Sep 17 00:00:00 2001 From: hniksic Date: Tue, 7 Oct 2003 16:53:31 -0700 Subject: [PATCH] [svn] Move fnmatch() to cmpt.c and don't use it under GNU libc. --- src/ChangeLog | 12 +++ src/Makefile.in | 11 ++- src/cmpt.c | 182 ++++++++++++++++++++++++++++++++++++++ src/fnmatch.c | 228 ------------------------------------------------ src/fnmatch.h | 46 ---------- src/ftp.c | 15 +++- src/http.c | 1 - src/recur.c | 1 - src/sysdep.h | 41 +++++++-- src/utils.c | 13 ++- src/utils.h | 1 + 11 files changed, 261 insertions(+), 290 deletions(-) delete mode 100644 src/fnmatch.c delete mode 100644 src/fnmatch.h diff --git a/src/ChangeLog b/src/ChangeLog index 3528831b..91905e6e 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,15 @@ +2003-10-08 Hrvoje Niksic + + * ftp.c (has_insecure_name_p): Define it here. + + * utils.c (has_wildcards_p): Define it here. + + * sysdep.h: Declare fnmatch-related macros here, if not using + system fnmatch(). Update .c files to not declare fnmatch.h + directly. + + * cmpt.c (fnmatch): Moved here. Use it only under non-GNU libc. + 2003-10-08 Hrvoje Niksic * getopt.c: Newer version, imported from Free libit. diff --git a/src/Makefile.in b/src/Makefile.in index 4ae47fa6..01e1f93a 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -72,7 +72,7 @@ OPIE_OBJ = @OPIE_OBJ@ SSL_OBJ = @SSL_OBJ@ GETOPT_OBJ = @GETOPT_OBJ@ -OBJ = $(ALLOCA) cmpt$o connect$o convert$o cookies$o fnmatch$o \ +OBJ = $(ALLOCA) cmpt$o connect$o convert$o cookies$o \ ftp$o ftp-basic$o ftp-ls$o $(OPIE_OBJ) $(GETOPT_OBJ) hash$o \ headers$o host$o html-parse$o html-url$o http$o init$o \ log$o main$o $(MD5_OBJ) netrc$o progress$o rbuf$o recur$o \ @@ -157,14 +157,13 @@ cmpt$o: wget.h sysdep.h options.h safe-ctype.h connect$o: wget.h sysdep.h options.h safe-ctype.h utils.h connect.h host.h convert$o: wget.h convert.h url.h recur.h utils.h hash.h cookies$o: wget.h sysdep.h options.h safe-ctype.h cookies.h hash.h url.h utils.h -fnmatch$o: wget.h sysdep.h options.h safe-ctype.h fnmatch.h ftp-basic$o: wget.h sysdep.h options.h safe-ctype.h utils.h rbuf.h connect.h \ host.h ftp.h ftp-ls$o: wget.h sysdep.h options.h safe-ctype.h utils.h ftp.h rbuf.h host.h \ url.h ftp-opie$o: wget.h sysdep.h options.h safe-ctype.h gen-md5.h ftp$o: wget.h sysdep.h options.h safe-ctype.h utils.h url.h rbuf.h retr.h \ - ftp.h host.h connect.h fnmatch.h netrc.h + ftp.h host.h connect.h netrc.h gen-md5$o: wget.h sysdep.h options.h safe-ctype.h gen-md5.h gen_sslfunc$o: wget.h sysdep.h options.h safe-ctype.h utils.h connect.h host.h \ url.h @@ -177,7 +176,7 @@ host$o: wget.h sysdep.h options.h safe-ctype.h utils.h host.h url.h hash.h html-parse$o: wget.h sysdep.h options.h safe-ctype.h html-parse.h html-url$o: wget.h sysdep.h options.h safe-ctype.h html-parse.h url.h utils.h http$o: wget.h sysdep.h options.h safe-ctype.h utils.h url.h host.h rbuf.h \ - retr.h headers.h connect.h host.h fnmatch.h netrc.h gen_sslfunc.h \ + retr.h headers.h connect.h host.h netrc.h gen_sslfunc.h \ cookies.h gen-md5.h init$o: wget.h sysdep.h options.h safe-ctype.h utils.h init.h host.h recur.h \ netrc.h cookies.h progress.h @@ -192,12 +191,12 @@ progress$o: wget.h sysdep.h options.h safe-ctype.h progress.h utils.h retr.h \ rbuf$o: wget.h sysdep.h options.h safe-ctype.h rbuf.h connect.h host.h \ gen_sslfunc.h recur$o: wget.h sysdep.h options.h safe-ctype.h url.h recur.h utils.h retr.h \ - rbuf.h ftp.h host.h fnmatch.h hash.h + rbuf.h ftp.h host.h hash.h res$o: wget.h sysdep.h options.h safe-ctype.h utils.h hash.h url.h retr.h res.h retr$o: wget.h sysdep.h options.h safe-ctype.h utils.h retr.h rbuf.h url.h \ recur.h ftp.h host.h connect.h hash.h snprintf$o: safe-ctype.h safe-ctype$o: safe-ctype.h url$o: wget.h sysdep.h options.h safe-ctype.h utils.h url.h host.h hash.h -utils$o: wget.h sysdep.h options.h safe-ctype.h utils.h fnmatch.h hash.h +utils$o: wget.h sysdep.h options.h safe-ctype.h utils.h hash.h version$o: diff --git a/src/cmpt.c b/src/cmpt.c index 6edf8402..ea1f44ae 100644 --- a/src/cmpt.c +++ b/src/cmpt.c @@ -43,6 +43,11 @@ so, delete this exception statement from your version. */ #endif #include +#include +#ifndef errno +extern int errno; +#endif + #include "wget.h" #ifndef HAVE_STRERROR @@ -1470,3 +1475,180 @@ memmove (char *dest, const char *source, unsigned length) #endif /* not HAVE_MEMMOVE */ #endif /* 0 */ + +/* fnmatch is a POSIX function, but we include an implementation for + the sake of systems that don't have it. Furthermore, according to + anecdotal evidence, historical implementations of fnmatch are buggy + and unreliable. So we use our version, except when compiling under + systems where fnmatch is known to work (currently glibc.) */ + +#ifndef SYSTEM_FNMATCH + +#define __FNM_FLAGS (FNM_PATHNAME | FNM_NOESCAPE | FNM_PERIOD) + +/* Match STRING against the filename pattern PATTERN, returning zero + if it matches, FNM_NOMATCH if not. This implementation comes from + an earlier version of GNU Bash. (It doesn't make sense to update + it with a newer version because it adds a lot of features Wget + doesn't use or care about.) */ + +int +fnmatch (const char *pattern, const char *string, int flags) +{ + register const char *p = pattern, *n = string; + register char c; + + if ((flags & ~__FNM_FLAGS) != 0) + { + errno = EINVAL; + return (-1); + } + + while ((c = *p++) != '\0') + { + switch (c) + { + case '?': + if (*n == '\0') + return (FNM_NOMATCH); + else if ((flags & FNM_PATHNAME) && *n == '/') + return (FNM_NOMATCH); + else if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) + return (FNM_NOMATCH); + break; + + case '\\': + if (!(flags & FNM_NOESCAPE)) + c = *p++; + if (*n != c) + return (FNM_NOMATCH); + break; + + case '*': + if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) + return (FNM_NOMATCH); + + for (c = *p++; c == '?' || c == '*'; c = *p++, ++n) + if (((flags & FNM_PATHNAME) && *n == '/') || + (c == '?' && *n == '\0')) + return (FNM_NOMATCH); + + if (c == '\0') + return (0); + + { + char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; + for (--p; *n != '\0'; ++n) + if ((c == '[' || *n == c1) && + fnmatch (p, n, flags & ~FNM_PERIOD) == 0) + return (0); + return (FNM_NOMATCH); + } + + case '[': + { + /* Nonzero if the sense of the character class is + inverted. */ + register int not; + + if (*n == '\0') + return (FNM_NOMATCH); + + if ((flags & FNM_PERIOD) && *n == '.' && + (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) + return (FNM_NOMATCH); + + /* Make sure there is a closing `]'. If there isn't, + the `[' is just a character to be matched. */ + { + register const char *np; + + for (np = p; np && *np && *np != ']'; np++); + + if (np && !*np) + { + if (*n != '[') + return (FNM_NOMATCH); + goto next_char; + } + } + + not = (*p == '!' || *p == '^'); + if (not) + ++p; + + c = *p++; + while (1) + { + register char cstart = c, cend = c; + + if (!(flags & FNM_NOESCAPE) && c == '\\') + cstart = cend = *p++; + + if (c == '\0') + /* [ (unterminated) loses. */ + return (FNM_NOMATCH); + + c = *p++; + + if ((flags & FNM_PATHNAME) && c == '/') + /* [/] can never match. */ + return (FNM_NOMATCH); + + if (c == '-' && *p != ']') + { + cend = *p++; + if (!(flags & FNM_NOESCAPE) && cend == '\\') + cend = *p++; + if (cend == '\0') + return (FNM_NOMATCH); + c = *p++; + } + + if (*n >= cstart && *n <= cend) + goto matched; + + if (c == ']') + break; + } + if (!not) + return (FNM_NOMATCH); + + next_char: + 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 == '\\') + /* 1003.2d11 is unclear if this is right. %%% */ + ++p; + } + if (not) + return (FNM_NOMATCH); + } + break; + + default: + if (c != *n) + return (FNM_NOMATCH); + } + + ++n; + } + + if (*n == '\0') + return (0); + + return (FNM_NOMATCH); +} + +#endif /* not SYSTEM_FNMATCH */ diff --git a/src/fnmatch.c b/src/fnmatch.c deleted file mode 100644 index 39bf6e01..00000000 --- a/src/fnmatch.c +++ /dev/null @@ -1,228 +0,0 @@ -/* Pattern matching (globbing). - Copyright (C) 1991, 1996, 1997 Free Software Foundation, Inc. - -This file is part of GNU Wget. - -GNU Wget is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -GNU Wget 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Wget; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -In addition, as a special exception, the Free Software Foundation -gives permission to link the code of its release of Wget with the -OpenSSL project's "OpenSSL" library (or with modified versions of it -that use the same license as the "OpenSSL" library), and distribute -the linked executables. You must obey the GNU General Public License -in all respects for all of the code used other than "OpenSSL". If you -modify this file, you may extend this exception to your version of the -file, but you are not obligated to do so. If you do not wish to do -so, delete this exception statement from your version. */ - -/* NOTE: Some Un*xes have their own fnmatch() -- yet, they are - reportedly unreliable and buggy. Thus I chose never to use it; - this version (from GNU Bash) is used unconditionally. */ - -#include - -#include -#include "wget.h" -#ifdef HAVE_STRING_H -# include -#else -# include -#endif /* HAVE_STRING_H */ -#include "fnmatch.h" - -/* Match STRING against the filename pattern PATTERN, returning zero - if it matches, FNM_NOMATCH if not. */ -int -fnmatch (const char *pattern, const char *string, int flags) -{ - register const char *p = pattern, *n = string; - register char c; - - if ((flags & ~__FNM_FLAGS) != 0) - { - errno = EINVAL; - return (-1); - } - - while ((c = *p++) != '\0') - { - switch (c) - { - case '?': - if (*n == '\0') - return (FNM_NOMATCH); - else if ((flags & FNM_PATHNAME) && *n == '/') - return (FNM_NOMATCH); - else if ((flags & FNM_PERIOD) && *n == '.' && - (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) - return (FNM_NOMATCH); - break; - - case '\\': - if (!(flags & FNM_NOESCAPE)) - c = *p++; - if (*n != c) - return (FNM_NOMATCH); - break; - - case '*': - if ((flags & FNM_PERIOD) && *n == '.' && - (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) - return (FNM_NOMATCH); - - for (c = *p++; c == '?' || c == '*'; c = *p++, ++n) - if (((flags & FNM_PATHNAME) && *n == '/') || - (c == '?' && *n == '\0')) - return (FNM_NOMATCH); - - if (c == '\0') - return (0); - - { - char c1 = (!(flags & FNM_NOESCAPE) && c == '\\') ? *p : c; - for (--p; *n != '\0'; ++n) - if ((c == '[' || *n == c1) && - fnmatch (p, n, flags & ~FNM_PERIOD) == 0) - return (0); - return (FNM_NOMATCH); - } - - case '[': - { - /* Nonzero if the sense of the character class is - inverted. */ - register int not; - - if (*n == '\0') - return (FNM_NOMATCH); - - if ((flags & FNM_PERIOD) && *n == '.' && - (n == string || ((flags & FNM_PATHNAME) && n[-1] == '/'))) - return (FNM_NOMATCH); - - /* Make sure there is a closing `]'. If there isn't, - the `[' is just a character to be matched. */ - { - register const char *np; - - for (np = p; np && *np && *np != ']'; np++); - - if (np && !*np) - { - if (*n != '[') - return (FNM_NOMATCH); - goto next_char; - } - } - - not = (*p == '!' || *p == '^'); - if (not) - ++p; - - c = *p++; - while (1) - { - register char cstart = c, cend = c; - - if (!(flags & FNM_NOESCAPE) && c == '\\') - cstart = cend = *p++; - - if (c == '\0') - /* [ (unterminated) loses. */ - return (FNM_NOMATCH); - - c = *p++; - - if ((flags & FNM_PATHNAME) && c == '/') - /* [/] can never match. */ - return (FNM_NOMATCH); - - if (c == '-' && *p != ']') - { - cend = *p++; - if (!(flags & FNM_NOESCAPE) && cend == '\\') - cend = *p++; - if (cend == '\0') - return (FNM_NOMATCH); - c = *p++; - } - - if (*n >= cstart && *n <= cend) - goto matched; - - if (c == ']') - break; - } - if (!not) - return (FNM_NOMATCH); - - next_char: - 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 == '\\') - /* 1003.2d11 is unclear if this is right. %%% */ - ++p; - } - if (not) - return (FNM_NOMATCH); - } - break; - - default: - if (c != *n) - return (FNM_NOMATCH); - } - - ++n; - } - - if (*n == '\0') - return (0); - - return (FNM_NOMATCH); -} - -/* Return non-zero if S has a leading '/' or contains '../' */ -int -has_insecure_name_p (const char *s) -{ - if (*s == '/') - return 1; - - if (strstr(s, "../") != 0) - return 1; - - return 0; -} - -/* Return non-zero if S contains globbing wildcards (`*', `?', `[' or - `]'). */ -int -has_wildcards_p (const char *s) -{ - for (; *s; s++) - if (*s == '*' || *s == '?' || *s == '[' || *s == ']') - return 1; - return 0; -} diff --git a/src/fnmatch.h b/src/fnmatch.h deleted file mode 100644 index a3449aaa..00000000 --- a/src/fnmatch.h +++ /dev/null @@ -1,46 +0,0 @@ -/* Declarations for fnmatch.c. - Copyright (C) 1991, 1995, 1996 Free Software Foundation, Inc. - -This file is part of GNU Wget. - -GNU Wget is free software; you can redistribute it and/or modify -it under the terms of the GNU General Public License as published by -the Free Software Foundation; either version 2 of the License, or -(at your option) any later version. - -GNU Wget 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 General Public License for more details. - -You should have received a copy of the GNU General Public License -along with Wget; if not, write to the Free Software -Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. - -In addition, as a special exception, the Free Software Foundation -gives permission to link the code of its release of Wget with the -OpenSSL project's "OpenSSL" library (or with modified versions of it -that use the same license as the "OpenSSL" library), and distribute -the linked executables. You must obey the GNU General Public License -in all respects for all of the code used other than "OpenSSL". If you -modify this file, you may extend this exception to your version of the -file, but you are not obligated to do so. If you do not wish to do -so, delete this exception statement from your version. */ - -#ifndef FNMATCH_H -#define FNMATCH_H - -/* 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. */ -#define __FNM_FLAGS (FNM_PATHNAME|FNM_NOESCAPE|FNM_PERIOD) - -/* Value returned by `fnmatch' if STRING does not match PATTERN. */ -#define FNM_NOMATCH 1 - -int fnmatch PARAMS ((const char *, const char *, int)); -int has_insecure_name_p PARAMS ((const char *s)); -int has_wildcards_p PARAMS ((const char *)); - -#endif /* FNMATCH_H */ diff --git a/src/ftp.c b/src/ftp.c index d99ddb71..5061d9cf 100644 --- a/src/ftp.c +++ b/src/ftp.c @@ -52,7 +52,6 @@ so, delete this exception statement from your version. */ #include "ftp.h" #include "connect.h" #include "host.h" -#include "fnmatch.h" #include "netrc.h" #include "convert.h" /* for downloaded_file */ @@ -1593,6 +1592,18 @@ Not descending to `%s' as it is excluded/not-included.\n"), newdir); return RETROK; } +/* Return non-zero if S has a leading '/' or contains '../' */ +static int +has_insecure_name_p (const char *s) +{ + if (*s == '/') + return 1; + + if (strstr(s, "../") != 0) + return 1; + + return 0; +} /* A near-top-level function to retrieve the files in a directory. The function calls ftp_get_listing, to get a linked list of files. @@ -1634,7 +1645,7 @@ ftp_retrieve_glob (struct url *u, ccon *con, int action) f = orig; while (f) { - if (has_insecure_name_p(f->name)) + if (has_insecure_name_p (f->name)) { logprintf (LOG_VERBOSE, _("Rejecting `%s'.\n"), f->name); f = delelement (f, &start); diff --git a/src/http.c b/src/http.c index 92043a57..cd48d9b9 100644 --- a/src/http.c +++ b/src/http.c @@ -62,7 +62,6 @@ so, delete this exception statement from your version. */ #include "retr.h" #include "headers.h" #include "connect.h" -#include "fnmatch.h" #include "netrc.h" #ifdef HAVE_SSL # include "gen_sslfunc.h" diff --git a/src/recur.c b/src/recur.c index 9a9e8ba1..007354b7 100644 --- a/src/recur.c +++ b/src/recur.c @@ -49,7 +49,6 @@ so, delete this exception statement from your version. */ #include "utils.h" #include "retr.h" #include "ftp.h" -#include "fnmatch.h" #include "host.h" #include "hash.h" #include "res.h" diff --git a/src/sysdep.h b/src/sysdep.h index c47a243f..a42cfa8a 100644 --- a/src/sysdep.h +++ b/src/sysdep.h @@ -182,8 +182,9 @@ void *memmove (); #endif /* SunOS brain damage -- for some reason, SunOS header files fail to - declare the functions below, which causes all kinds of problems - (compiling errors) with pointer arithmetic and similar. + declare the functions below, which causes all kinds of problems, + most notably compilation errors when using pointer arithmetic on + their return values. This used to be only within `#ifdef STDC_HEADERS', but it got tripped on other systems (AIX), thus causing havoc. Fortunately, @@ -191,16 +192,16 @@ void *memmove (); added an extra `#ifdef sun' guard. */ #ifndef STDC_HEADERS #ifdef sun -#ifndef __cplusplus +#ifndef __SVR4 /* exclude Solaris */ char *strstr (); char *strchr (); char *strrchr (); char *strtok (); char *strdup (); void *memcpy (); -#endif /* not __cplusplus */ +#endif /* not __SVR4 */ #endif /* sun */ -#endif /* STDC_HEADERS */ +#endif /* not STDC_HEADERS */ /* Some systems (Linux libc5, "NCR MP-RAS 3.0", and others) don't provide MAP_FAILED, a symbolic constant for the value returned by @@ -212,4 +213,34 @@ void *memcpy (); # define MAP_FAILED ((void *) -1) #endif +/* Enable system fnmatch only on systems where we know it works: + currently glibc-based systems and Solaris. One could add more, but + fnmatch is not that large, so it might be better to play it + safe. */ +#if defined __GLIBC__ && __GLIBC__ >= 2 +# define SYSTEM_FNMATCH +#endif +#ifdef solaris +# define SYSTEM_FNMATCH +#endif + +#ifdef SYSTEM_FNMATCH +# include +#else /* not SYSTEM_FNMATCH */ +/* Define fnmatch flags. Undef them first to avoid warnings in case + an evil library include chose to include system fnmatch.h. */ +# undef FNM_PATHNAME +# undef FNM_NOESCAPE +# undef FNM_PERIOD +# undef FNM_NOMATCH + +# 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. */ +# define FNM_NOMATCH 1 + +/* Declare the function minimally. */ +int fnmatch (); +#endif + #endif /* SYSDEP_H */ diff --git a/src/utils.c b/src/utils.c index b563d40a..c78b1708 100644 --- a/src/utils.c +++ b/src/utils.c @@ -92,7 +92,6 @@ so, delete this exception statement from your version. */ #include "wget.h" #include "utils.h" -#include "fnmatch.h" #include "hash.h" #ifndef errno @@ -874,6 +873,18 @@ suffix (const char *str) return NULL; } +/* Return non-zero if S contains globbing wildcards (`*', `?', `[' or + `]'). */ + +int +has_wildcards_p (const char *s) +{ + for (; *s; s++) + if (*s == '*' || *s == '?' || *s == '[' || *s == ']') + return 1; + return 0; +} + /* Return non-zero if FNAME ends with a typical HTML suffix. The following (case-insensitive) suffixes are presumed to be HTML files: diff --git a/src/utils.h b/src/utils.h index 0783602d..01a1d3de 100644 --- a/src/utils.h +++ b/src/utils.h @@ -80,6 +80,7 @@ int acceptable PARAMS ((const char *)); int accdir PARAMS ((const char *s, enum accd)); char *suffix PARAMS ((const char *s)); int match_tail PARAMS ((const char *, const char *, int)); +int has_wildcards_p PARAMS ((const char *)); int has_html_suffix_p PARAMS ((const char *)); -- 2.39.2