filesystem: dir: check casefold directory flag

This commit is contained in:
Alibek Omarov 2022-12-26 21:27:04 +03:00
parent 256fe7ede9
commit 339711c3c7

View File

@ -13,14 +13,23 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
*/
#include "build.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#if XASH_POSIX
#include <unistd.h>
#endif
#include <errno.h>
#include <stddef.h>
#if XASH_POSIX
#include <unistd.h>
#include <sys/ioctl.h>
#endif
#if XASH_LINUX
#include <linux/fs.h>
#ifndef FS_CASEFOLD_FL // for compatibility with older distros
#define FS_CASEFOLD_FL 0x40000000
#endif // FS_CASEFOLD_FL
#endif // XASH_LINUX
#include "port.h"
#include "filesystem_internal.h"
#include "crtlib.h"
@ -41,6 +50,29 @@ typedef struct dir_s
struct dir_s *entries; // sorted
} dir_t;
static qboolean Platform_GetDirectoryCaseSensitivity( const char *dir )
{
#if XASH_WIN32
return false;
#elif XASH_LINUX && defined( FS_IOC_GETFLAGS )
int flags = 0;
int fd;
fd = open( dir, O_RDONLY | O_NONBLOCK );
if( fd < 0 )
return true;
if( ioctl( fd, FS_IOC_GETFLAGS, &flags ) < 0 )
return true;
close( fd );
return !FBitSet( flags, FS_CASEFOLD_FL );
#else
return true;
#endif
}
static int FS_SortDirEntries( const void *_a, const void *_b )
{
const dir_t *a = _a;
@ -82,10 +114,6 @@ static void FS_InitDirEntries( dir_t *dir, const stringlist_t *list )
static void FS_PopulateDirEntries( dir_t *dir, const char *path )
{
#if XASH_WIN32 // Windows is always case insensitive
dir->numentries = DIRENTRY_CASEINSENSITIVE;
dir->entries = NULL;
#else
stringlist_t list;
if( !FS_SysFolderExists( path ))
@ -95,6 +123,13 @@ static void FS_PopulateDirEntries( dir_t *dir, const char *path )
return;
}
if( !Platform_GetDirectoryCaseSensitivity( path ))
{
dir->numentries = DIRENTRY_CASEINSENSITIVE;
dir->entries = NULL;
return;
}
stringlistinit( &list );
listdirectory( &list, path );
if( !list.numstrings )
@ -107,7 +142,6 @@ static void FS_PopulateDirEntries( dir_t *dir, const char *path )
FS_InitDirEntries( dir, &list );
}
stringlistfreecontents( &list );
#endif
}
static int FS_FindDirEntry( dir_t *dir, const char *name )