char *Sys_FindFirst (const char *path, unsigned musthave, unsigned canhave) { struct dirent *d; char *p; if (fdir) Sys_Error ("Sys_BeginFind without close"); // COM_FilePath (path, findbase); strcpy(findbase, path); if ((p = strrchr(findbase, '/')) != NULL) { *p = 0; strcpy(findpattern, p + 1); } else strcpy(findpattern, "*"); if (strcmp(findpattern, "*.*") == 0) strcpy(findpattern, "*"); if ((fdir = opendir(findbase)) == NULL) return NULL; while ((d = readdir(fdir)) != NULL) { if (!*findpattern || glob_match(findpattern, d->d_name)) { // if (*findpattern) // printf("%s matched %s\n", findpattern, d->d_name); if (CompareAttributes(findbase, d->d_name, musthave, canhave)) { sprintf (findpath, "%s/%s", findbase, d->d_name); return findpath; } } } return NULL; }
/* ----------------------------------------------------------------------------- Function: FS_FindNext -Continues a file search from a previous call to the FS_FindFirst function. Parameters: musthave -[in] File or directory must have these attributes. canthave- [in] File or directory can not have these attributes. Returns: On success string of file name or directory, otherwise NULL. Notes: ----------------------------------------------------------------------------- */ PUBLIC char *FS_FindNext( W32 musthave, W32 canthave ) { struct dirent *d; if( fdir == NULL ) { return NULL; } while( (d = readdir( fdir ) ) != NULL) { if( ! *findpattern || glob_match( findpattern, d->d_name ) ) { if( ! *findbase ) { my_strlcpy( findpath, d->d_name, sizeof( findpath ) ); } else { my_snprintf( findpath, sizeof( findpath ), "%s/%s", findbase, d->d_name ); } if( CompareAttributes( findpath, musthave, canthave ) ) { return findpath; } } } return NULL; }
/* * R_GlobFilter */ static bool R_GlobFilter( const char *pattern, const char *value ) { if( *pattern && !glob_match( pattern, value, 0 ) ) { return false; } return true; }
/* * Compare file attributes (musthave and canthave) in packed files. If * "output" is not NULL, "size" is greater than zero and the file matches the * attributes then a copy of the matching string will be placed there (with * SFF_SUBDIR it changes). */ qboolean ComparePackFiles(const char *findname, const char *name, unsigned musthave, unsigned canthave, char *output, int size) { qboolean retval; char *ptr; char buffer[MAX_OSPATH]; Q_strlcpy(buffer, name, sizeof(buffer)); if ((canthave & SFF_SUBDIR) && (name[strlen(name) - 1] == '/')) { return false; } if (musthave & SFF_SUBDIR) { if ((ptr = strrchr(buffer, '/')) != NULL) { *ptr = '\0'; } else { return false; } } if ((musthave & SFF_HIDDEN) || (canthave & SFF_HIDDEN)) { if ((ptr = strrchr(buffer, '/')) == NULL) { ptr = buffer; } if (((musthave & SFF_HIDDEN) && (ptr[1] != '.')) || ((canthave & SFF_HIDDEN) && (ptr[1] == '.'))) { return false; } } if (canthave & SFF_RDONLY) { return false; } retval = glob_match((char *)findname, buffer); if (retval && (output != NULL)) { Q_strlcpy(output, buffer, size); } return retval; }
/* * Match pkg against pattern, return 1 if matching, 0 else */ int pkg_match(const char *pattern, const char *pkg) { if (!quick_pkg_match(pattern, pkg)) return 0; if (strchr(pattern, '{') != (char *) NULL) { /* emulate csh-type alternates */ return alternate_match(pattern, pkg); } if (strpbrk(pattern, "<>") != (char *) NULL) { int ret; /* perform relational dewey match on version number */ ret = dewey_match(pattern, pkg); if (ret < 0) errx(EXIT_FAILURE, "dewey_match returned error"); return ret; } if (strpbrk(pattern, "*?[]") != (char *) NULL) { /* glob match */ if (glob_match(pattern, pkg)) return 1; } /* no alternate, dewey or glob match -> simple compare */ if (simple_match(pattern, pkg)) return 1; /* globbing patterns and simple matches may be specified with or * without the version number, so check for both cases. */ { char *pattern_ver; int retval; pattern_ver = xasprintf("%s-[0-9]*", pattern); retval = glob_match(pattern_ver, pkg); free(pattern_ver); return retval; } }
/* ----------------------------------------------------------------------------- Function: FS_FindFirstFile() -Searches a directory for a file. Parameters: path -[in] Pointer to a NUL-terminated string that specifies a valid directory or path and file name. musthave -[in] File or directory must have these attributes. canthave- [in] File or directory can not have these attributes. Returns: On success string of file name or directory, otherwise NULL. Notes: ----------------------------------------------------------------------------- */ PUBLIC char *FS_FindFirst( const char *path, W32 musthave, W32 canthave ) { struct dirent *d; char *p; p; if( fdir ) { Com_Printf( "FS_FindFirst without close\n" ); return NULL; } FS_FilePath( (char *)path, findbase ); my_strlcpy( (char *)findpattern, FS_SkipPath( (char *)path ), sizeof( findpattern ) ); if( ! *findbase ) { if( (fdir = opendir( "." )) == NULL ) { return NULL; } } else { if( (fdir = opendir( findbase )) == NULL ) { return NULL; } } while( (d = readdir( fdir )) != NULL ) { if( ! *findpattern || glob_match( findpattern, d->d_name ) ) { if( ! *findbase ) { my_strlcpy( findpath, d->d_name, sizeof( findpath ) ); } else { my_snprintf( findpath, sizeof( findpath ), "%s/%s", findbase, d->d_name ); } if( CompareAttributes( findpath, musthave, canthave ) ) { return findpath; } } } return NULL; }
static void filter_sources(StringArray& labels, StringArray& sources, const string& pattern) { assert(labels.size() == sources.size()); StringArray new_labels; StringArray new_sources; for (int i = 0; i < labels.size(); i++) { if (glob_match(pattern.chars(), labels[i].chars(), 0) || glob_match(pattern.chars(), sources[i].chars(), 0)) { new_labels += labels[i]; new_sources += sources[i]; } } labels = new_labels; sources = new_sources; }
static BAN * is_banned (LIST * bans, const char *nick, const char *host) { char mask[256]; snprintf (mask, sizeof (mask), "%s!%s", nick, host); for (; bans; bans = bans->next) { if (glob_match (((BAN *) bans->data)->target, mask)) return bans->data; } return 0; }
char *Sys_FindNext (unsigned musthave, unsigned canhave) { struct dirent *d; if (fdir == NULL) return NULL; while ((d = readdir(fdir)) != NULL) { if (!*findpattern || glob_match(findpattern, d->d_name)) { if (CompareAttributes(findbase, d->d_name, musthave, canhave)) { sprintf (findpath, "%s/%s", findbase, d->d_name); return findpath; } } } return NULL; }
/* the rest of the pattern segments */ #endif /* ANSI_PROTOTYPES */ { char *saved_end = path_end; /* saved to be resored */ char *pat; /* current pattern segment */ struct stat st; /* to check if file exists */ #ifdef GLOBDEBUG ffprintf(STDDBG,"do_glob: path = '%s', pat = '%s'\n", main_path, *gpat ); #endif for ( ; (pat = *gpat) != 0 && no_glob(pat); gpat++ ) { #ifdef GLOBDEBUG ffprintf(STDDBG,"no_glob: path = '%s', pat = '%s'\n", main_path, pat ); #endif *path_end = '/'; (void)strcpy(path_end+1, pat); path_end += strlen(pat) + 1; if (GLOBSTAT(main_path, &st) != 0 ) { *saved_end = '\0'; return; } } if (pat) matchdir(path_end, gpat); else add_name(); *saved_end = '\0'; return; } static void #ifndef ANSI_PROTOTYPES matchdir(path_end, gpat) char *path_end; /* ptr to end of main_path */ char **gpat; /* the rest of the pattern segments */ #else /* ANSI_PROTOTYPES */ matchdir(char *path_end, char **gpat) /* ptr to end of main_path */ /* the rest of the pattern segments */ #endif /* ANSI_PROTOTYPES */ { char *x; /* scratch */ VOIDDIR *dirp; /* for directory reading */ VOIDDIRENT *dp; /* directory entry */ struct stat st; /* to determine files type */ #ifdef GLOBDEBUG ffprintf(STDDBG,"matchdir: path = '%s', pat = '%s'\n", main_path, *gpat ); #endif if ((dirp = OPENDIR(main_path)) == NULL) return; *path_end = '/'; while ((dp = READDIR(dirp)) != NULL) { char *dirname; x = dirname = GETNAME(dp); /* was dp->d_name */ if (*x == '.' && (*++x == '\0' || (*x == '.' && *++x == '\0'))) continue; if (*dirname == '.' && **gpat != '.') continue; (void)strcpy(path_end + 1, dirname); if (glob_match(*gpat, dirname)) { /* this is a match */ if ( *(gpat+1) == 0 ) { /* and it is the last */ add_name(); /* so eat it */ continue; } if (GLOBSTAT(main_path, &st) == 0 /* else not the last */ && (st.st_mode & S_IFMT) == S_IFDIR) do_glob(path_end + strlen(dirname) + 1, gpat + 1); } } (void)CLOSEDIR(dirp); *path_end = '\0'; }
/* Like glob_match, but match PATTERN against any final segment of TEXT. */ static int glob_match_after_star( char *pattern, char *text ) { register char *p = pattern, *t = text; register char c, c1; while( (c = *p++) == '?' || c == '*' ) { if( c == '?' && *t++ == '\0' ) { return 0; } } if( c == '\0' ) { return 1; } if( c == '\\' ) { c1 = *p; } else { c1 = c; } while( 1 ) { if( (c == '[' || *t == c1) && glob_match( p - 1, t ) ) { return 1; } if( *t++ == '\0' ) { return 0; } } }
/** * \brief Find all files matching a given pattern. * \param dirname The name of the directory to explore. * \param pattern The pattern of the name of the files to find. * \param offset The length of the path to the root directory. * \param m The maximum number of files to find. * \param result (out) The paths of the files. * * \sa glob_match */ void bf::path_configuration::find_all_files_in_dir ( const std::string& dirname, const std::string& pattern, std::size_t offset, std::size_t m, std::list<std::string>& result ) const { const boost::filesystem::path path( dirname ); CLAW_PRECOND( boost::filesystem::is_directory(path) ); boost::filesystem::directory_iterator it(path); const boost::filesystem::directory_iterator eit; for ( ; (it!=eit) && (result.size() < m); ++it ) { const std::string entry_path( it->path().string() ); if ( boost::filesystem::is_directory(*it) ) { if ( glob_potential_match(pattern, entry_path, offset) ) find_all_files_in_dir(entry_path, pattern, offset, m, result); } else if ( glob_match(pattern, entry_path, offset) ) result.push_back( entry_path ); } } // path_configuration::find_all_files_in_dir()
int Com_GlobMatch( const char *pattern, const char *text, const qboolean casecmp ) { return glob_match( pattern, text, casecmp ); }
/* ** Check to see if the directory named in zPath is the top of a checkout. ** In other words, check to see if directory pPath contains a file named ** "_vcs_" or ".fslckout". Return true or false. */ int vfile_top_of_checkout(const char *zPath){ char *zFile; int fileFound = 0; zFile = mprintf("%s/_vcs_", zPath); fileFound = file_size(zFile)>=1024; vcs_free(zFile); if( !fileFound ){ zFile = mprintf("%s/.fslckout", zPath); fileFound = file_size(zFile)>=1024; vcs_free(zFile); } /* ** Load into table SFILE the name of every ordinary file in ** the directory pPath. Omit the first nPrefix characters of ** of pPath when inserting into the SFILE table. ** ** Subdirectories are scanned recursively. ** Omit files named in VFILE. ** ** Files whose names begin with "." are omitted unless allFlag is true. ** ** Any files or directories that match the glob pattern pIgnore are ** excluded from the scan. Name matching occurs after the first ** nPrefix characters are elided from the filename. */ void vfile_scan(Blob *pPath, int nPrefix, int allFlag, Glob *pIgnore){ DIR *d; int origSize; const char *zDir; struct dirent *pEntry; int skipAll = 0; static Stmt ins; static int depth = 0; char *zMbcs; origSize = blob_size(pPath); if( pIgnore ){ blob_appendf(pPath, "/"); if( glob_match(pIgnore, &blob_str(pPath)[nPrefix+1]) ) skipAll = 1; blob_resize(pPath, origSize); } if( skipAll ) return; if( depth==0 ){ db_prepare(&ins, "INSERT OR IGNORE INTO sfile(x) SELECT :file" " WHERE NOT EXISTS(SELECT 1 FROM vfile WHERE pathname=:file)" ); } depth++; zDir = blob_str(pPath); zMbcs = vcs_utf8_to_mbcs(zDir); d = opendir(zMbcs); if( d ){ while( (pEntry=readdir(d))!=0 ){ char *zPath; char *zUtf8; if( pEntry->d_name[0]=='.' ){ if( !allFlag ) continue; if( pEntry->d_name[1]==0 ) continue; if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue; } zUtf8 = vcs_mbcs_to_utf8(pEntry->d_name); blob_appendf(pPath, "/%s", zUtf8); vcs_mbcs_free(zUtf8); zPath = blob_str(pPath); if( glob_match(pIgnore, &zPath[nPrefix+1]) ){ /* do nothing */ }else if( file_wd_isdir(zPath)==1 ){ if( !vfile_top_of_checkout(zPath) ){ vfile_scan(pPath, nPrefix, allFlag, pIgnore); } }else if( file_wd_isfile_or_link(zPath) ){ db_bind_text(&ins, ":file", &zPath[nPrefix+1]); db_step(&ins); db_reset(&ins); } blob_resize(pPath, origSize); } closedir(d); } vcs_mbcs_free(zMbcs); depth--; if( depth==0 ){ db_finalize(&ins); } }
/* ** Scans the specified base directory for any directories within it, while ** keeping a count of how many files they each contains, either directly or ** indirectly. ** ** Subdirectories are scanned recursively. ** Omit files named in VFILE. ** ** Directories whose names begin with "." are omitted unless the SCAN_ALL ** flag is set. ** ** Any directories that match the glob patterns pIgnore* are excluded from ** the scan. Name matching occurs after the first nPrefix characters are ** elided from the filename. ** ** Returns the total number of files found. */ int vfile_dir_scan( Blob *pPath, /* Base directory to be scanned */ int nPrefix, /* Number of bytes in base directory name */ unsigned scanFlags, /* Zero or more SCAN_xxx flags */ Glob *pIgnore1, /* Do not add directories that match this GLOB */ Glob *pIgnore2, /* Omit directories matching this GLOB too */ Glob *pIgnore3 /* Omit directories matching this GLOB too */ ){ int result = 0; DIR *d; int origSize; struct dirent *pEntry; int skipAll = 0; static Stmt ins; static Stmt upd; static int depth = 0; void *zNative; origSize = blob_size(pPath); if( pIgnore1 || pIgnore2 || pIgnore3 ){ blob_appendf(pPath, "/"); if( glob_match(pIgnore1, &blob_str(pPath)[nPrefix+1]) ) skipAll = 1; if( glob_match(pIgnore2, &blob_str(pPath)[nPrefix+1]) ) skipAll = 1; if( glob_match(pIgnore3, &blob_str(pPath)[nPrefix+1]) ) skipAll = 1; blob_resize(pPath, origSize); } if( skipAll ) return result; if( depth==0 ){ db_multi_exec("DROP TABLE IF EXISTS dscan_temp;" "CREATE TEMP TABLE dscan_temp(" " x TEXT PRIMARY KEY %s, y INTEGER)", filename_collation()); db_prepare(&ins, "INSERT OR IGNORE INTO dscan_temp(x, y) SELECT :file, :count" " WHERE NOT EXISTS(SELECT 1 FROM vfile WHERE" " pathname GLOB :file || '/*' %s)", filename_collation() ); db_prepare(&upd, "UPDATE OR IGNORE dscan_temp SET y = coalesce(y, 0) + 1" " WHERE x=:file %s", filename_collation() ); } depth++; zNative = fossil_utf8_to_filename(blob_str(pPath)); d = opendir(zNative); if( d ){ while( (pEntry=readdir(d))!=0 ){ char *zOrigPath; char *zPath; char *zUtf8; if( pEntry->d_name[0]=='.' ){ if( (scanFlags & SCAN_ALL)==0 ) continue; if( pEntry->d_name[1]==0 ) continue; if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue; } zOrigPath = mprintf("%s", blob_str(pPath)); zUtf8 = fossil_filename_to_utf8(pEntry->d_name); blob_appendf(pPath, "/%s", zUtf8); zPath = blob_str(pPath); if( glob_match(pIgnore1, &zPath[nPrefix+1]) || glob_match(pIgnore2, &zPath[nPrefix+1]) || glob_match(pIgnore3, &zPath[nPrefix+1]) ){ /* do nothing */ }else if( file_wd_isdir(zPath)==1 ){ if( (scanFlags & SCAN_NESTED) || !vfile_top_of_checkout(zPath) ){ char *zSavePath = mprintf("%s", zPath); int count = vfile_dir_scan(pPath, nPrefix, scanFlags, pIgnore1, pIgnore2, pIgnore3); db_bind_text(&ins, ":file", &zSavePath[nPrefix+1]); db_bind_int(&ins, ":count", count); db_step(&ins); db_reset(&ins); fossil_free(zSavePath); result += count; /* found X normal files? */ } }else if( file_wd_isfile_or_link(zPath) ){ db_bind_text(&upd, ":file", zOrigPath); db_step(&upd); db_reset(&upd); result++; /* found 1 normal file */ } fossil_filename_free(zUtf8); blob_resize(pPath, origSize); fossil_free(zOrigPath); } closedir(d); } fossil_filename_free(zNative); depth--; if( depth==0 ){ db_finalize(&upd); db_finalize(&ins); } return result; }
/* * Adds the directory to the head of the path, then loads and adds pak1.pak * pak2.pak ... * * Extended all functionality to include Quake III .pk3 */ void FS_AddGameDirectory(const char *dir) { char **list; /* File list. */ char path[MAX_OSPATH]; /* Path to PAK / PK3. */ int i, j; /* Loop counters. */ int nfiles; /* Number of files in list. */ fsSearchPath_t *search; /* Search path. */ fsPack_t *pack; /* PAK / PK3 file. */ pack = NULL; /* Set game directory. */ Q_strlcpy(fs_gamedir, dir, sizeof(fs_gamedir)); /* Create directory if it does not exist. */ FS_CreatePath(fs_gamedir); /* Add the directory to the search path. */ search = Z_Malloc(sizeof(fsSearchPath_t)); Q_strlcpy(search->path, dir, sizeof(search->path)); search->next = fs_searchPaths; fs_searchPaths = search; /* Add numbered pack files in sequence. */ for (i = 0; i < sizeof(fs_packtypes) / sizeof(fs_packtypes[0]); i++) { for (j = 0; j < MAX_PAKS; j++) { Com_sprintf(path, sizeof(path), "%s/pak%d.%s", dir, j, fs_packtypes[i].suffix); switch (fs_packtypes[i].format) { case PAK: pack = FS_LoadPAK(path); break; #ifdef ZIP case PK3: pack = FS_LoadPK3(path); break; #endif } if (pack == NULL) { continue; } search = Z_Malloc(sizeof(fsSearchPath_t)); search->pack = pack; search->next = fs_searchPaths; fs_searchPaths = search; } } /* Add not numbered pack files. */ for (i = 0; i < sizeof(fs_packtypes) / sizeof(fs_packtypes[0]); i++) { Com_sprintf(path, sizeof(path), "%s/*.%s", dir, fs_packtypes[i].suffix); if ((list = FS_ListFiles(path, &nfiles, 0, SFF_SUBDIR)) == NULL) { continue; } Com_sprintf(path, sizeof(path), "%s/pak*.%s", dir, fs_packtypes[i].suffix); for (j = 0; j < nfiles - 1; j++) { /* Skip numbered packs. */ if (glob_match(path, list[j])) { continue; } switch (fs_packtypes[i].format) { case PAK: pack = FS_LoadPAK(list[j]); break; #ifdef ZIP case PK3: pack = FS_LoadPK3(list[j]); break; #endif } if (pack == NULL) { continue; } search = Z_Malloc(sizeof(fsSearchPath_t)); search->pack = pack; search->next = fs_searchPaths; fs_searchPaths = search; } FS_FreeList(list, nfiles); } }
/* ** Load into table SFILE the name of every ordinary file in ** the directory pPath. Omit the first nPrefix characters of ** of pPath when inserting into the SFILE table. ** ** Subdirectories are scanned recursively. ** Omit files named in VFILE. ** ** Files whose names begin with "." are omitted unless the SCAN_ALL ** flag is set. ** ** Any files or directories that match the glob patterns pIgnore* ** are excluded from the scan. Name matching occurs after the ** first nPrefix characters are elided from the filename. */ void vfile_scan( Blob *pPath, /* Directory to be scanned */ int nPrefix, /* Number of bytes in directory name */ unsigned scanFlags, /* Zero or more SCAN_xxx flags */ Glob *pIgnore1, /* Do not add files that match this GLOB */ Glob *pIgnore2 /* Omit files matching this GLOB too */ ){ DIR *d; int origSize; struct dirent *pEntry; int skipAll = 0; static Stmt ins; static int depth = 0; void *zNative; origSize = blob_size(pPath); if( pIgnore1 || pIgnore2 ){ blob_appendf(pPath, "/"); if( glob_match(pIgnore1, &blob_str(pPath)[nPrefix+1]) ) skipAll = 1; if( glob_match(pIgnore2, &blob_str(pPath)[nPrefix+1]) ) skipAll = 1; blob_resize(pPath, origSize); } if( skipAll ) return; if( depth==0 ){ db_prepare(&ins, "INSERT OR IGNORE INTO sfile(x) SELECT :file" " WHERE NOT EXISTS(SELECT 1 FROM vfile WHERE" " pathname=:file %s)", filename_collation() ); } depth++; zNative = fossil_utf8_to_filename(blob_str(pPath)); d = opendir(zNative); if( d ){ while( (pEntry=readdir(d))!=0 ){ char *zPath; char *zUtf8; if( pEntry->d_name[0]=='.' ){ if( (scanFlags & SCAN_ALL)==0 ) continue; if( pEntry->d_name[1]==0 ) continue; if( pEntry->d_name[1]=='.' && pEntry->d_name[2]==0 ) continue; } zUtf8 = fossil_filename_to_utf8(pEntry->d_name); blob_appendf(pPath, "/%s", zUtf8); zPath = blob_str(pPath); if( glob_match(pIgnore1, &zPath[nPrefix+1]) || glob_match(pIgnore2, &zPath[nPrefix+1]) ){ /* do nothing */ }else if( file_wd_isdir(zPath)==1 ){ if( !vfile_top_of_checkout(zPath) ){ vfile_scan(pPath, nPrefix, scanFlags, pIgnore1, pIgnore2); } }else if( file_wd_isfile_or_link(zPath) ){ if( (scanFlags & SCAN_TEMP)==0 || is_temporary_file(zUtf8) ){ db_bind_text(&ins, ":file", &zPath[nPrefix+1]); db_step(&ins); db_reset(&ins); } } fossil_filename_free(zUtf8); blob_resize(pPath, origSize); } closedir(d); } fossil_filename_free(zNative); depth--; if( depth==0 ){ db_finalize(&ins); } }
/* returns >0 if the pattern matches, 0 if the pattern does not match. * the match is case-insensitive */ int glob_match(const char *pattern, const char *s) { const char *ptr; /* Added by winter_mute */ #if defined(USE_PROTNET) || defined(USE_INVALID_CLIENTS) || defined(USE_INVALID_NICKS) if( #ifdef USE_PROTNET strcmp(pattern, global.protnet) == 0 #endif /* global.invalidClients is not alone, add the || */ #if defined(USE_PROTNET) && defined(USE_INVALID_CLIENTS) || strcmp(pattern, global.invalidClients) == 0 #elif defined(USE_INVALID_CLIENTS) strcmp(pattern, global.invalidClients) == 0 #endif /* global.invalidNicks is not alone, add the || */ #if(defined(USE_PROTNET) || defined(USE_INVALID_CLIENTS)) && defined(USE_INVALID_NICKS) || strcmp(pattern, global.invalidNicks) == 0 #elif defined(USE_INVALID_NICKS) strcmp(pattern, global.invalidNicks) == 0 #endif #if(defined(USE_PROTNET) || defined(USE_INVALID_CLIENTS)) && defined(USE_INVALID_NICKS) || strcmp(pattern, global.setServerNicks) == 0 #elif defined(USE_INVALID_NICKS) strcmp(pattern, global.setServerNicks) == 0 #endif ) { const char *delim = ","; char *p_tmp = STRDUP(pattern); /* In order to preserve the pointer, we now assign it to another var */ char *p_tmpptr = p_tmp; /* Seperate the string into either , or SPACE, and loop throug each one */ char *val = strsep(&p_tmp, delim); if(p_tmp) { do { if(glob_match(val, s)) { /* Might be a leak when not freed */ FREE(p_tmpptr); return 1; } } while ((val = strsep(&p_tmp, delim)) != NULL); /* No match, free mem and return 0 */ if(p_tmpptr != NULL) FREE(p_tmpptr); return 0; } /* Wouldn't split it up, so free mem and let normal glob take care of it */ else if(p_tmpptr != NULL) FREE(p_tmpptr); } #endif /* either identifier exists */ while (*pattern || *s) { if(*pattern == '*') { while (*pattern == '*' || *pattern == '?') pattern++; if(!*pattern) { /* match to end of string */ return 1; } /* recursively attempt to match the rest of the string, using the * longest match first */ ptr = s + strlen(s); for (;;) { while (ptr > s && tolower (*(ptr - 1)) != tolower (*pattern)) ptr--; if(ptr == s) return 0; /* no match */ if(glob_match(pattern + 1, ptr)) return 1; ptr--; } /* not reached */ } else if(*pattern == '?' || tolower (*pattern) == tolower (*s)) { pattern++; s++; } else return 0; /* no match */ } return((*pattern || *s) ? 0 : 1); }
static int glob_match(char *expr, char *str) { /* this is non-destructive */ int min,max,st; if (!expr || !str) return 0; while(*expr != '\0' && *str != '\0') { /* get next element */ switch (*expr) { case '[': expr++; st = 0; while (*expr != ']' && *expr != '\0') { min = *expr++; if (min == '\\') { if (*expr == '\0') return 0; /* syntax error */ min = *expr++; } if (*expr == '-') { /* find max */ expr++; if (*expr == '\\') expr++; max = *expr++; } else max = min; if (min == '\0' || max == '\0') return 0; /* syntax error */ if (*str >= min && *str <= max) { str++; st = 1; break; } } if (!st) return 0; /* nothing in the range matched */ /* skip to end of range */ while (*expr != ']' && *expr != '\0') expr++; if (*expr != ']') return 0; /* syntax error */ expr++; break; case '{': { char *e_rem, *sub_end; expr++; /* find end of expression */ e_rem = expr; while (*e_rem && *e_rem != '}') { if (*e_rem == '\\') e_rem++; if (*e_rem) e_rem++; } if (e_rem) e_rem++; /* e_rem now points to whatever is after the multiple choice */ /* pick out each subexpression and try it */ while (expr < e_rem) { /* find the end of the next subexpression */ sub_end = expr; while(sub_end < e_rem && *sub_end != ',' && *sub_end != '}') { if (*sub_end == '\\') sub_end++; if (sub_end < e_rem) sub_end++; } /* sub_end now points to the character just beyond the last of the next subexpr */ if (strncmp(expr,str,sub_end-expr) == 0 && glob_match(e_rem,str+(sub_end-expr))) return 1; /* this subexpression works with the remaining */ /* if we get here, then this subexpression doesn't work out */ expr = sub_end+1; if (expr > e_rem) expr = e_rem; } /* if we get here, then none of the choices worked out - the whole expression fails */ return 0; } break; case '?': if (*str == '\0') return 0; expr++; str++; break; case '*': expr++; /* special case - end of expr */ if (!*expr) return 1; /* nothing left in expression */ while (*str) { if (glob_match(expr,str)) return 1; str++; } return glob_match(expr,str); case '\\': expr++; /* fall-through */ default: if (*expr != *str) return 0; expr++; str++; } } if (*expr == '\0' && *str == '\0') return 1; else /* didn't end in the same spot */ return 0; }
/* Like glob_match, but match PATTERN against any final segment of TEXT. */ static int glob_match_after_star( const char *pattern, const char *text, const int casecmp ) { register const char *p = pattern, *t = text; register char c, c1; while( ( c = *p++ ) == '?' || c == '*' ) if( c == '?' && *t++ == '\0' ) return 0; if( c == '\0' ) return 1; if( c == '\\' ) c1 = *p; else c1 = c; while( 1 ) { if( ( c == '[' || ( casecmp ? ( *t == c1 ) : ( tolower( *t ) == tolower( c1 ) ) ) ) && glob_match( p - 1, t, casecmp ) ) return 1; if( *t++ == '\0' ) return 0; } }
/* glob_match matches pattern against string according to the normal * rules for shell globbing. It returns SUCCES if string matches * pattern, FAIL if it doesn't, and ERROR if pattern is illformed. * * To be more specific, a pattern can be: * ? which matches any single character * * which matches zero or more character * [...] which matches any single character in ... * [^...] which matches any single character not in ... * \x where x is any character, matches that character literally * x where x is any character except ? * [ and \, matches x * * Character within [...] can include single characters and ranges of * the form x-y, which matches any characters in the ranges x - y * inclusive. It is considered an error is y < x. An ] can be included * as the very first character in ..., and a - as the first (after a * possibly [) or last character in ... */ #define PSUCCES 2 #define SUCCES 1 #define FAIL 0 #define ERROR 0 #define NEXTP {if ( (p = *++pattern) == '\0') return ERROR;} int #ifndef ANSI_PROTOTYPES glob_match( pattern, string ) char *pattern; char *string; #else /* ANSI_PROTOTYPES */ glob_match(char *pattern, char *string) #endif /* ANSI_PROTOTYPES */ { char p; char seenstar = '\0'; for ( ; (p = *pattern); pattern++ ) { if ( p == '\\' ) { NEXTP; /* matches next char literally (but not \0) */ if ( p != *string++ ) return FAIL; /* string too short */ continue; } else if ( p == '?' ) { if ( *string++ ) /* matches any character */ continue; else return FAIL; /* string too short */ } else if ( p == '*' ) { seenstar = '\1'; continue; } else { if ( seenstar ) { int tmp; while ( *string ) { tmp = glob_match( pattern, string ); if ( tmp != FAIL ) return tmp; string++; } return FAIL; /* NOTREACHED */ } if ( p == '\0' ) return FAIL; if ( p == '[' ) { char s = *string++; char reverse = '\0'; char first, last; char gotcha = '\0'; NEXTP; if ( p == '^' ) { reverse = '\1'; NEXTP; } if ( p == ']' ) { /* special case */ gotcha = (s==p); NEXTP; } while ( p != ']' && !gotcha ) { first = p; NEXTP; if ( p == '-' && pattern[1] != ']' ) { NEXTP; last = p; NEXTP; } else last = first; if ( first > last ) return ERROR; gotcha = (first <= s && s <= last ); } while ( p != ']' ) NEXTP; if ( reverse ? gotcha : !gotcha ) return FAIL; } else if ( p != *string ) return FAIL; else string++; } } if ( seenstar ) return SUCCES; if ( *string ) return FAIL; return SUCCES; }