⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 bsd-glob.c

📁 功能强大的ftp服务器源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * Copyright (c) 1989, 1993 *	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. *//* Recursion and matches limiting by Frank Denis <j@pureftpd.org> *//* * glob(3) -- a superset of the one defined in POSIX 1003.2. * * The [!...] convention to negate a range is supported (SysV, Posix, ksh). * * Optional extra services, controlled by flags not defined by POSIX: * * GLOB_QUOTE: *    Escaping convention: \ inhibits any special meaning the following *    character might have (except \ at end of string is retained). * GLOB_MAGCHAR: *    Set in gl_flags if pattern contained a globbing character. * GLOB_NOMAGIC: *    Same as GLOB_NOCHECK, but it will only append pattern if it did *    not contain any magic characters.  [Used in csh style globbing] * GLOB_BRACE: *    expand {1,2}{a,b} to 1a 1b 2a 2b * gl_matchc: *    Number of matches in the current invocation of glob. */#include <config.h>#ifndef DISABLE_GLOBBING#include "ftpd.h"#ifdef HAVE_DIRENT_H# include <dirent.h>#endif#ifdef HAVE_SYS_NDIR_H# include <sys/ndir.h>#endif#ifdef HAVE_NDIR_H# include <ndir.h>#endif#include "bsd-glob.h"#ifdef WITH_DMALLOC# include <dmalloc.h>#endif#define    DOLLAR        '$'#define    DOT        '.'#define    EOS        '\0'#define    LBRACKET    '['#define    NOT        '!'#define    QUESTION    '?'#define    QUOTE        '\\'#define    RANGE        '-'#define    RBRACKET    ']'#define    SEP        '/'#define    STAR        '*'#ifdef USELESS_FOR_PUREFTPD# define    TILDE        '~'#endif#define    UNDERSCORE    '_'#define    LBRACE        '{'#define    RBRACE        '}'#define    SLASH        '/'#define    COMMA        ','#define    M_QUOTE        0x8000#define    M_PROTECT    0x4000#define    M_MASK        0xffff#define    M_ASCII        0x00fftypedef unsigned short Char;#define    CHAR(c)        ((Char)((c)&M_ASCII))#define    META(c)        ((Char)((c)|M_QUOTE))#define    M_ALL        META('*')#define    M_END        META(']')#define    M_NOT        META('!')#define    M_ONE        META('?')#define    M_RNG        META('-')#define    M_SET        META('[')#define    ismeta(c)    (((c)&M_QUOTE) != 0)static int compare(const void *, const void *);static int g_Ctoc(const Char *, char *, unsigned int);static int g_lstat(Char *, struct stat *);static DIR *g_opendir(Char *);static const Char *g_strchr(const Char *, int);static int glob0(const Char *, glob_t *);static int glob1(Char *, Char *, glob_t *, size_t *);static int glob2(Char *, Char *, Char *, Char *, Char *, Char *,                 glob_t *, size_t *, int);static int glob3(Char *, Char *, Char *, Char *, Char *,                 Char *, Char *, glob_t *, size_t *, int);static int globextend(const Char *, glob_t *, size_t *);#ifdef USELESS_FOR_PUREFTPDstatic const Char *globtilde(const Char *, Char *, size_t, glob_t *);#endifstatic int globexp1(const Char *, glob_t *, int);static int globexp2(const Char *, const Char *, glob_t *, int *, int);static int match(Char *, Char *, Char *);static int glob_(const char *pattern,                 int flags,                 int (*errfunc) (const char *, int),                 glob_t * pglob, unsigned long maxfiles, int maxdepth);static int glob_(const char *pattern,                 int flags,                 int (*errfunc) (const char *, int),                 glob_t * pglob, unsigned long maxfiles, int maxdepth){    const unsigned char *patnext;    int c;    Char *bufnext, *bufend, patbuf[MAXPATHLEN + 1];    pglob->gl_maxdepth = maxdepth;    pglob->gl_maxfiles = maxfiles;    patnext = (const unsigned char *) pattern;    pglob->gl_flags = flags & ~GLOB_MAGCHAR;    pglob->gl_errfunc = errfunc;    pglob->gl_matchc = 0;    pglob->gl_pathc = 0;    pglob->gl_pathv = NULL;    bufnext = patbuf;    bufend = bufnext + MAXPATHLEN;    if (flags & GLOB_NOESCAPE) {        while (bufnext < bufend && (c = *patnext++) != EOS) {            *bufnext++ = (Char) c;	}    } else {        /* Protect the quoted characters. */        while (bufnext < bufend && (c = *patnext++) != EOS) {            if (c == QUOTE) {                if ((c = *patnext++) == EOS) {                    c = QUOTE;                    --patnext;                }                *bufnext++ = (Char) (c | M_PROTECT);            } else {                *bufnext++ = (Char) c;	    }        }    }    *bufnext = EOS;    if (flags & GLOB_BRACE) {        return globexp1(patbuf, pglob, 0);    }    return glob0(patbuf, pglob);    }intglob(const char *pattern,     int flags, int (*errfunc) (const char *, int), glob_t * pglob){    return glob_(pattern, flags, errfunc, pglob, (unsigned long) -1, 0);}intsglob(char *pattern,      int flags,      int (*errfunc) (const char *, int),      glob_t * pglob, unsigned long maxfiles, int maxdepth){    simplify(pattern);    return glob_(pattern, flags, errfunc, pglob, maxfiles, maxdepth);}/* * Expand recursively a glob {} pattern. When there is no more expansion * invoke the standard globbing routine to glob the rest of the magic * characters */static int globexp1(const Char * pattern, glob_t * pglob, int recursion){    const Char *ptr = pattern;    int rv;    if (pglob->gl_maxdepth > 0 && recursion > pglob->gl_maxdepth) {        errno = 0;        return 0;    }    /* Protect a single {}, for find(1), like csh */    if (pattern[0] == LBRACE && pattern[1] == RBRACE && pattern[2] == EOS)        return glob0(pattern, pglob);    while ((ptr =            (const Char *) g_strchr((const Char *) ptr, LBRACE)) != NULL) {        if (!globexp2(ptr, pattern, pglob, &rv, recursion + 1))            return rv;    }    return glob0(pattern, pglob);}/* * Recursive brace globbing helper. Tries to expand a single brace. * If it succeeds then it invokes globexp1 with the new pattern. * If it fails then it tries to glob the rest of the pattern and returns. */static intglobexp2(const Char * ptr,         const Char * pattern, glob_t * pglob, int *rv, int recursion){    int i;    Char *lm, *ls;    const Char *pe, *pm, *pl;    Char patbuf[MAXPATHLEN + 1];    if (pglob->gl_maxdepth > 0 && recursion > pglob->gl_maxdepth) {        errno = 0;        return 0;    }    /* copy part up to the brace */    for (lm = patbuf, pm = pattern; pm != ptr; *lm++ = *pm++);    *lm = EOS;    ls = lm;    /* Find the balanced brace */    for (i = 0, pe = ++ptr; *pe; pe++)        if (*pe == LBRACKET) {            /* Ignore everything between [] */            for (pm = pe++; *pe != RBRACKET && *pe != EOS; pe++);            if (*pe == EOS) {                /*                 * We could not find a matching RBRACKET.                 * Ignore and just look for RBRACE                 */                pe = pm;            }        } else if (*pe == LBRACE) {            i++;        } else if (*pe == RBRACE) {            if (i == 0)                break;            i--;        }    /* Non matching braces; just glob the pattern */    if (i != 0 || *pe == EOS) {        *rv = glob0(patbuf, pglob);        return 0;    }    for (i = 0, pl = pm = ptr; pm <= pe; pm++) {        switch (*pm) {        case LBRACKET:            /* Ignore everything between [] */            for (pl = pm++; *pm != RBRACKET && *pm != EOS; pm++);            if (*pm == EOS) {                /*                 * We could not find a matching RBRACKET.                 * Ignore and just look for RBRACE                 */                pm = pl;            }            break;        case LBRACE:            i++;            break;        case RBRACE:            if (i) {                i--;                break;            }            /* FALLTHROUGH */        case COMMA:            if (i && *pm == COMMA)                break;            else {                /* Append the current string */                for (lm = ls; (pl < pm); *lm++ = *pl++);                /*                 * Append the rest of the pattern after the                 * closing brace                 */                for (pl = pe + 1; (*lm++ = *pl++) != EOS;);                /* Expand the current pattern */                *rv = globexp1(patbuf, pglob, recursion + 1);                /* move after the comma, to the next string */                pl = pm + 1;            }            break;        default:            break;        }    }    *rv = 0;    return 0;}#ifdef USELESS_FOR_PUREFTPD/* * expand tilde from the passwd file. */static const Char *globtilde(const Char * pattern,                             Char * patbuf,                             size_t patbuf_len, glob_t * pglob){    struct passwd *pwd;    char *h;    const Char *p;    Char *b, *eb;    if (*pattern != TILDE || !(pglob->gl_flags & GLOB_TILDE))        return pattern;    /* Copy up to the end of the string or / */    eb = &patbuf[patbuf_len - 1];    for (p = pattern + 1, h = (char *) patbuf;         h < (char *) eb && *p && *p != SLASH; *h++ = *p++);    *h = EOS;#if 0    if (h == (char *) eb)        return what;#endif    if (((char *) patbuf)[0] == EOS) {        /*         * handle a plain ~ or ~/ by expanding $HOME         * first and then trying the password file         */        if (issetugid() != 0 || (h = getenv("HOME")) == NULL) {            if ((pwd = getpwuid(getuid())) == NULL) {                return pattern;            } else {                h = pwd->pw_dir;            }        }    } else {        /*         * Expand a ~user         */        if ((pwd = getpwnam((char *) patbuf)) == NULL) {            return pattern;        } else {            h = pwd->pw_dir;        }    }    /* Copy the home directory */    for (b = patbuf; b < eb && *h; *b++ = *h++);    /* Append the rest of the pattern */    while (b < eb && (*b++ = *p++) != EOS);    *b = EOS;    return patbuf;}#endif/* * The main glob() routine: compiles the pattern (optionally processing * quotes), calls glob1() to do the real pattern matching, and finally * sorts the list (unless unsorted operation is requested).  Returns 0 * if things went well, nonzero if errors occurred.  It is not an error * to find no matches. */static int glob0(const Char * pattern, glob_t * pglob){    const Char *qpatnext;    int c, err, oldpathc;    Char *bufnext, patbuf[MAXPATHLEN + 1];    size_t limit = 0;#ifdef USELESS_FOR_PUREFTPD    qpatnext = globtilde(pattern, patbuf, MAXPATHLEN + 1, pglob);#else

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -