diff options
author | ridiculousfish <corydoras@ridiculousfish.com> | 2012-10-15 18:16:47 -0700 |
---|---|---|
committer | ridiculousfish <corydoras@ridiculousfish.com> | 2012-10-15 18:16:47 -0700 |
commit | 833abc27cc8653d92c4d275c042f35ced0ea3f94 (patch) | |
tree | 98b6af707453a688e6c4dbb258eca2f219ddfbf7 /wildcard.cpp | |
parent | 3d5a3f03fa160edd0423ab6e8e93ba43c56b97a8 (diff) |
Make wildcards beginning with dots not match . and ..
Diffstat (limited to 'wildcard.cpp')
-rw-r--r-- | wildcard.cpp | 52 |
1 files changed, 32 insertions, 20 deletions
diff --git a/wildcard.cpp b/wildcard.cpp index db42fadc..d32c8e01 100644 --- a/wildcard.cpp +++ b/wildcard.cpp @@ -143,29 +143,36 @@ int wildcard_has( const wchar_t *str, int internal ) \param wc The wildcard. \param is_first Whether files beginning with dots should not be matched against wildcards. */ -static int wildcard_match2( const wchar_t *str, +static bool wildcard_match2(const wchar_t *str, const wchar_t *wc, - int is_first ) + bool is_first ) { if( *str == 0 && *wc==0 ) - return 1; + return true; + + /* Hackish fix for https://github.com/fish-shell/fish-shell/issues/270. Prevent wildcards from matching . or .., but we must still allow literal matches. */ + if (is_first && contains(str, L".", L"..")) + { + /* The string is '.' or '..'. Return true if the wildcard exactly matches. */ + return ! wcscmp(str, wc); + } if( *wc == ANY_STRING || *wc == ANY_STRING_RECURSIVE) { /* Ignore hidden file */ if( is_first && *str == L'.' ) { - return 0; + return false; } /* Try all submatches */ do { - if( wildcard_match2( str, wc+1, 0 ) ) - return 1; + if( wildcard_match2( str, wc+1, false ) ) + return true; } while( *(str++) != 0 ); - return 0; + return false; } else if( *str == 0 ) { @@ -173,23 +180,23 @@ static int wildcard_match2( const wchar_t *str, End of string, but not end of wildcard, and the next wildcard element is not a '*', so this is not a match. */ - return 0; + return false; } if( *wc == ANY_CHAR ) { if( is_first && *str == L'.' ) { - return 0; + return false; } - return wildcard_match2( str+1, wc+1, 0 ); + return wildcard_match2( str+1, wc+1, false ); } if( *wc == *str ) - return wildcard_match2( str+1, wc+1, 0 ); + return wildcard_match2( str+1, wc+1, false ); - return 0; + return false; } /** @@ -303,9 +310,9 @@ bool wildcard_complete(const wcstring &str, } -int wildcard_match( const wcstring &str, const wcstring &wc ) +bool wildcard_match( const wcstring &str, const wcstring &wc ) { - return wildcard_match2( str.c_str(), wc.c_str(), 1 ); + return wildcard_match2( str.c_str(), wc.c_str(), true ); } /** @@ -684,7 +691,11 @@ typedef std::pair<dev_t, ino_t> file_id_t; This function traverses the relevant directory tree looking for matches, and recurses when needed to handle wildcrards spanning - multiple components and recursive wildcards. + multiple components and recursive wildcards. + + Because this function calls itself recursively with substrings, + it's important that the parameters be raw pointers instead of wcstring, + which would be too expensive to construct for all substrings. */ static int wildcard_expand_internal( const wchar_t *wc, const wchar_t *base_dir, @@ -709,7 +720,7 @@ static int wildcard_expand_internal( const wchar_t *wc, /* Variables for testing for presense of recursive wildcards */ const wchar_t *wc_recursive; - int is_recursive; + bool is_recursive; /* Slightly mangled version of base_dir */ const wchar_t *dir_string; @@ -843,7 +854,7 @@ static int wildcard_expand_internal( const wchar_t *wc, } else { - if( wildcard_match2( name, wc, 1 ) ) + if( wildcard_match2( name, wc, true ) ) { const wcstring long_name = make_path(base_dir, next); int skip = 0; @@ -938,7 +949,7 @@ static int wildcard_expand_internal( const wchar_t *wc, Test if the file/directory name matches the whole wildcard element, i.e. regular matching. */ - int whole_match = wildcard_match2( name, wc_str, 1 ); + int whole_match = wildcard_match2( name, wc_str, true ); int partial_match = 0; /* @@ -951,7 +962,7 @@ static int wildcard_expand_internal( const wchar_t *wc, { const wchar_t *end = wcschr( wc, ANY_STRING_RECURSIVE ); wchar_t *wc_sub = wcsndup( wc, end-wc+1); - partial_match = wildcard_match2( name, wc_sub, 1 ); + partial_match = wildcard_match2( name, wc_sub, true ); free( wc_sub ); } @@ -974,8 +985,9 @@ static int wildcard_expand_internal( const wchar_t *wc, { // Insert a "file ID" into visited_files // If the insertion fails, we've already visited this file (i.e. a symlink loop) + // If we're not recursive, insert anyways (in case we loop back around in a future recursive segment), but continue on; the idea being that literal path components should still work const file_id_t file_id(buf.st_dev, buf.st_ino); - if( S_ISDIR(buf.st_mode) && visited_files.insert(file_id).second) + if( S_ISDIR(buf.st_mode) && (visited_files.insert(file_id).second || ! is_recursive)) { size_t new_len = wcslen( new_dir ); new_dir[new_len] = L'/'; |