const char *DoWildCard( const char *base ) /***********************************************/ { PGROUP pg; struct dirent *entry; if( base != NULL ) { /* clean up from previous invocation */ DoWildCardClose(); if( strpbrk( base, WILD_METAS ) == NULL ) { return( base ); } // create directory name and pattern path = MallocSafe( _MAX_PATH ); pattern = MallocSafe( _MAX_PATH ); strcpy( path, base ); FixName( path ); _splitpath2( path, pg.buffer, &pg.drive, &pg.dir, &pg.fname, &pg.ext ); _makepath( path, pg.drive, pg.dir, ".", NULL ); // create file name pattern _makepath( pattern, NULL, NULL, pg.fname, pg.ext ); parent = opendir( path ); if( parent == NULL ) { DoWildCardClose(); return( base ); } } if( parent == NULL ) { return( NULL ); } assert( path != NULL && parent != NULL ); while( (entry = readdir( parent )) != NULL ) { #ifndef __UNIX__ if( ( entry->d_attr & IGNORE_MASK ) == 0 ) { #endif if( __fnmatch( pattern, entry->d_name ) ) { break; } #ifndef __UNIX__ } #endif } if( entry == NULL ) { DoWildCardClose(); return( base ); } _splitpath2( path, pg.buffer, &pg.drive, &pg.dir, &pg.fname, &pg.ext ); _makepath( path, pg.drive, pg.dir, entry->d_name, NULL ); return( path ); }
ap_fnmatch(const char *pattern, const char *string, int flags) { int e; if (strnlen(pattern, PATH_MAX) == PATH_MAX || strnlen(string, PATH_MAX) == PATH_MAX) return (FNM_NOMATCH); e = __fnmatch(pattern, string, flags, __FNM_MAX_RECUR); if (e == -1) e = FNM_NOMATCH; return (e); }
static int __fnmatch( char *pattern, char *string ) /************************************************** * OS specific compare function FNameCmpChr * must be used for file names */ { char *p; int len; int star_char; int i; /* * check pattern section with wildcard characters */ star_char = 0; while( IS_WILDCARD_CHAR( pattern ) ) { if( *pattern == '?' ) { if( *string == 0 ) { return( 0 ); } string++; } else { star_char = 1; } pattern++; } if( *pattern == 0 ) { if( (*string == 0) || star_char ) { return( 1 ); } else { return( 0 ); } } /* * check pattern section with exact match * ( all characters except wildcards ) */ p = pattern; len = 0; do { if( star_char ) { if( string[len] == 0 ) { return( 0 ); } len++; } else { if( FNameCmpChr( *pattern, *string ) != 0 ) { return( 0 ); } string++; } pattern++; } while( *pattern && !IS_WILDCARD_CHAR( pattern ) ); if( star_char == 0 ) { /* * match is OK, try next pattern section */ return( __fnmatch( pattern, string ) ); } else { /* * star pattern section, try locate exact match */ while( *string ) { if( FNameCmpChr( *p, *string ) == 0 ) { for( i = 1; i < len; i++ ) { if( FNameCmpChr( *(p + i), *(string + i) ) != 0 ) { break; } } if( i == len ) { /* * if rest doesn't match, find next occurence */ if( __fnmatch( pattern, string + len ) ) { return( 1 ); } } } string++; } return( 0 ); } }
static int __fnmatch( char *pattern, char *string ) /*************************************************/ { char *p; int len; int star_char; int i; /* * check pattern section with wildcard characters */ star_char = 0; while( ( *pattern == '*' ) || ( *pattern == '?' ) ) { if( *pattern == '?' ) { if( *string == 0 ) { return( 0 ); } string++; } else { star_char = 1; } pattern++; } if( *pattern == 0 ) { if( ( *string == 0 ) || star_char ) { return( 1 ); } else { return( 0 ); } } /* * check pattern section with exact match * ( all characters except wildcards ) */ p = pattern; len = 0; do { if( star_char ) { if( string[ len ] == 0 ) { return( 0 ); } len++; } else { if( *pattern != *string ) { return( 0 ); } string++; } pattern++; } while( *pattern && ( *pattern != '*' ) && ( *pattern != '?' ) ); if( star_char == 0 ) { /* * match is OK, try next pattern section */ return( __fnmatch( pattern, string ) ); } else { /* * star pattern section, try locate exact match */ while( *string ) { if( *p == *string ) { for( i = 1; i < len; i++ ) { if( *( p + i ) != *( string + i ) ) { break; } } if( i == len ) { /* * if rest doesn't match, find next occurence */ if( __fnmatch( pattern, string + len ) ) { return( 1 ); } } } string++; } return( 0 ); } }
static copy_entry *BuildList( char *src, char *dst, bool test_abit ) { copy_entry *head; copy_entry *curr; copy_entry **owner; char *end; char buff[_MAX_PATH2]; char full[_MAX_PATH]; char srcdir[_MAX_PATH]; char *drive; char *dir; char *fn; char *ext; DIR *directory; struct dirent *dent; #ifndef __UNIX__ FILE *fp; unsigned attr; #else struct stat statsrc, statdst; int dstrc, srcrc; char pattern[_MAX_PATH]; #endif strcpy( srcdir, src ); end = &dst[strlen( dst ) - 1]; while( end[0] == ' ' || end[0] == '\t' ) { --end; } end[1] = '\0'; if( strchr( srcdir, '*' ) == NULL && strchr( srcdir, '?' ) == NULL ) { /* no wild cards */ head = Alloc( sizeof( *head ) ); head->next = NULL; _fullpath( head->src, srcdir, sizeof( head->src ) ); switch( *end ) { case '\\': case '/': /* need to append source file name */ _splitpath2( srcdir, buff, &drive, &dir, &fn, &ext ); _makepath( full, NULL, dst, fn, ext ); _fullpath( head->dst, full, sizeof( head->dst ) ); break; default: _fullpath( head->dst, dst, sizeof( head->dst ) ); break; } if( test_abit ) { #ifndef __UNIX__ fp = fopen( head->dst, "rb" ); if( fp != NULL ) fclose( fp ); _dos_getfileattr( head->src, &attr ); if( !( attr & _A_ARCH ) && fp != NULL ) { /* file hasn't changed */ free( head ); head = NULL; } #else /* Linux has (strangely) no 'archive' attribute, compare modification times */ dstrc = stat( head->dst, &statdst ); srcrc = stat( head->src, &statsrc ); if( (dstrc != -1) && (srcrc != -1) && (statdst.st_mtime == statsrc.st_mtime) ) { free( head ); head = NULL; } #endif } return( head ); } #ifdef __UNIX__ _splitpath2( srcdir, buff, &drive, &dir, &fn, &ext ); _makepath( srcdir, drive, dir, NULL, NULL ); _makepath( pattern, NULL, NULL, fn, ext ); #endif directory = opendir( srcdir ); if( directory == NULL ) { Log( FALSE, "Can not open source directory '%s': %s\n", srcdir, strerror( errno ) ); return( NULL ); } head = NULL; owner = &head; for( ;; ) { dent = readdir( directory ); if( dent == NULL ) break; #ifdef __UNIX__ { struct stat buf; size_t len = strlen( srcdir ); if( __fnmatch( pattern, dent->d_name ) == 0 ) continue; strcat( srcdir, dent->d_name ); stat( srcdir, &buf ); srcdir[len] = '\0'; if( S_ISDIR( buf.st_mode ) ) continue; } #else if( dent->d_attr & ( _A_SUBDIR | _A_VOLID ) ) continue; #endif curr = Alloc( sizeof( *curr ) ); curr->next = NULL; _splitpath2( srcdir, buff, &drive, &dir, &fn, &ext ); _makepath( full, drive, dir, dent->d_name, NULL ); _fullpath( curr->src, full, sizeof( curr->src ) ); strcpy( full, dst ); switch( *end ) { case '\\': case '/': strcat( full, dent->d_name ); break; } _fullpath( curr->dst, full, sizeof( curr->dst ) ); if( test_abit ) { #ifndef __UNIX__ fp = fopen( curr->dst, "rb" ); if( fp != NULL ) fclose( fp ); if( !(dent->d_attr & _A_ARCH) && fp != NULL ) { /* file hasn't changed */ free( curr ); continue; } #else /* Linux has (strangely) no 'archive' attribute, compare modification times */ dstrc = stat( curr->dst, &statdst ); srcrc = stat( curr->src, &statsrc ); if( (dstrc != -1) && (srcrc != -1) && (statdst.st_mtime == statsrc.st_mtime) ) { free( curr ); continue; } #endif } *owner = curr; owner = &curr->next; } return( head ); }
int __fnmatch(const char *pattern, const char *string, int flags, int recur) { const char *stringstart; char c, test; int e; if (recur-- == 0) return (-1); for (stringstart = string;;) { switch (c = *pattern++) { case EOS: return (*string == EOS ? 0 : FNM_NOMATCH); case '?': if (*string == EOS) return (FNM_NOMATCH); if (*string == '/' && (flags & FNM_PATHNAME)) return (FNM_NOMATCH); if (*string == '.' && (flags & FNM_PERIOD) && (string == stringstart || ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) return (FNM_NOMATCH); ++string; break; case '*': c = *pattern; /* Collapse multiple stars. */ while (c == '*') c = *++pattern; if (*string == '.' && (flags & FNM_PERIOD) && (string == stringstart || ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) return (FNM_NOMATCH); /* Optimize for pattern with * at end or before /. */ if (c == EOS) { if (flags & FNM_PATHNAME) return (strchr(string, '/') == NULL ? 0 : FNM_NOMATCH); else return (0); } else if (c == '/' && flags & FNM_PATHNAME) { if ((string = strchr(string, '/')) == NULL) return (FNM_NOMATCH); break; } /* General case, use recursion. */ while ((test = *string) != EOS) { e = __fnmatch(pattern, string, flags & ~FNM_PERIOD, recur); if (e != FNM_NOMATCH) return (e); if (test == '/' && flags & FNM_PATHNAME) break; ++string; } return (FNM_NOMATCH); case '[': if (*string == EOS) return (FNM_NOMATCH); if (*string == '/' && flags & FNM_PATHNAME) return (FNM_NOMATCH); if (*string == '.' && (flags & FNM_PERIOD) && (string == stringstart || ((flags & FNM_PATHNAME) && *(string - 1) == '/'))) return (FNM_NOMATCH); if ((pattern = rangematch(pattern, *string, flags)) == NULL) return (FNM_NOMATCH); ++string; break; case '\\': if (!(flags & FNM_NOESCAPE)) if ((c = *pattern++) == EOS) { c = '\\'; --pattern; } /* FALLTHROUGH */ default: if (flags & FNM_CASE_BLIND) { if (ap_tolower(c) != ap_tolower(*string)) return (FNM_NOMATCH); } else if (c != *string) return (FNM_NOMATCH); string++; break; } /* NOTREACHED */ } }