Fix Sys_ListFiles() on POSIX once again

Turned out that as "extension" (which is really more like a pattern
that matches the whole file) was even used with patterns like "*.*"
so we do proper matching using fnmatch() now - which is even easier
than the old way.
Now deleting savegames on POSIX works.
This commit is contained in:
Daniel Gibson 2013-01-04 14:33:17 +01:00
parent a405b37f13
commit cf8d287a4e

View file

@ -42,6 +42,7 @@ If you have questions concerning this license or the applicable additional terms
#include <termios.h> #include <termios.h>
#include <signal.h> #include <signal.h>
#include <fcntl.h> #include <fcntl.h>
#include <fnmatch.h>
// RB begin // RB begin
#if defined(__ANDROID__) #if defined(__ANDROID__)
@ -358,21 +359,23 @@ int Sys_ListFiles( const char* directory, const char* extension, idStrList& list
list.Clear(); list.Clear();
debug = cvarSystem->GetCVarBool( "fs_debug" ); debug = cvarSystem->GetCVarBool( "fs_debug" );
// DG: we use fnmatch for shell-style pattern matching
// DG: handle "*" as special case that matches everything // so the pattern should at least contain "*" to match everything,
// FIXME: handle * properly as a wildcase somewhere in the string? // the extension will be added behind that (if !dironly)
if( !extension || ( extension[0] == '*' && extension[1] == '\0' ) ) idStr pattern( "*" );
extension = "";
// DG end
// passing a slash as extension will find directories // passing a slash as extension will find directories
if( extension[0] == '/' && extension[1] == 0 ) if( extension[0] == '/' && extension[1] == 0 )
{ {
extension = "";
dironly = true; dironly = true;
} }
else
{
// so we have *<extension>, the same as in the windows code basically
pattern += extension;
}
// DG end
// search
// NOTE: case sensitivity of directory path can screw us up here // NOTE: case sensitivity of directory path can screw us up here
if( ( fdir = opendir( directory ) ) == NULL ) if( ( fdir = opendir( directory ) ) == NULL )
{ {
@ -399,8 +402,6 @@ int Sys_ListFiles( const char* directory, const char* extension, idStrList& list
return 0; return 0;
} }
int extLen = idStr::Length( extension );
while( readdir_r( fdir, entry, &d ) == 0 && d != NULL ) while( readdir_r( fdir, entry, &d ) == 0 && d != NULL )
{ {
// DG end // DG end
@ -410,14 +411,11 @@ int Sys_ListFiles( const char* directory, const char* extension, idStrList& list
if( !dironly ) if( !dironly )
{ {
// DG: the original code didn't work because d3 bfg abuses the extension // DG: the original code didn't work because d3 bfg abuses the extension
// to match whole filenames in the savegame-code, not just file extensions... // to match whole filenames and patterns in the savegame-code, not just file extensions...
// the extension must be the last chars of the filename // so just use fnmatch() which supports matching shell wildcard patterns ("*.foo" etc)
// so start matching at startPos = strlen(d->d_name) - strlen(extension) // if we should ever need case insensitivity, use FNM_CASEFOLD as third flag
int startPos = idStr::Length( d->d_name ) - extLen; if( fnmatch( pattern.c_str(), d->d_name, 0 ) != 0 )
// of course the extension can't match if it's longer than the filename, i.e. startPos < 0
if( startPos < 0 || idStr::FindText( d->d_name, extension, true, startPos ) < 0 )
continue; continue;
// DG end // DG end
} }
if( ( dironly && !( st.st_mode & S_IFDIR ) ) || if( ( dironly && !( st.st_mode & S_IFDIR ) ) ||