mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-10 10:08:18 +00:00
fix fs_listdir and fs_listdir_fileinfo with unicode on windows
This commit is contained in:
parent
75662b6c1a
commit
4a375242c5
|
@ -1987,19 +1987,38 @@ void net_unix_close(UNIXSOCKET sock)
|
|||
}
|
||||
#endif
|
||||
|
||||
int fs_listdir_info(const char *dir, FS_LISTDIR_INFO_CALLBACK cb, int type, void *user)
|
||||
#if defined (CONF_FAMILY_WINDOWS)
|
||||
static inline time_t filetime_to_unixtime(LPFILETIME filetime)
|
||||
{
|
||||
time_t t;
|
||||
ULARGE_INTEGER li;
|
||||
li.LowPart = filetime->dwLowDateTime;
|
||||
li.HighPart = filetime->dwHighDateTime;
|
||||
|
||||
li.QuadPart /= 10000000; // 100ns to 1s
|
||||
li.QuadPart -= 11644473600LL; // Windows epoch is in the past
|
||||
|
||||
t = li.QuadPart;
|
||||
return t == li.QuadPart ? t : (time_t)-1;
|
||||
}
|
||||
#endif
|
||||
|
||||
void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user)
|
||||
{
|
||||
#if defined(CONF_FAMILY_WINDOWS)
|
||||
WIN32_FIND_DATA finddata;
|
||||
WIN32_FIND_DATAW finddata;
|
||||
HANDLE handle;
|
||||
char buffer[1024 * 2];
|
||||
char buffer[IO_MAX_PATH_LENGTH];
|
||||
char buffer2[IO_MAX_PATH_LENGTH];
|
||||
WCHAR wBuffer[IO_MAX_PATH_LENGTH];
|
||||
int length;
|
||||
|
||||
str_format(buffer, sizeof(buffer), "%s/*", dir);
|
||||
MultiByteToWideChar(CP_UTF8, 0, buffer, IO_MAX_PATH_LENGTH, wBuffer, IO_MAX_PATH_LENGTH);
|
||||
|
||||
handle = FindFirstFileA(buffer, &finddata);
|
||||
|
||||
handle = FindFirstFileW(wBuffer, &finddata);
|
||||
if(handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
str_format(buffer, sizeof(buffer), "%s/", dir);
|
||||
length = str_length(buffer);
|
||||
|
@ -2007,87 +2026,105 @@ int fs_listdir_info(const char *dir, FS_LISTDIR_INFO_CALLBACK cb, int type, void
|
|||
/* add all the entries */
|
||||
do
|
||||
{
|
||||
str_copy(buffer + length, finddata.cFileName, (int)sizeof(buffer) - length);
|
||||
if(cb(finddata.cFileName, fs_getmtime(buffer), fs_is_dir(buffer), type, user))
|
||||
break;
|
||||
} while(FindNextFileA(handle, &finddata));
|
||||
|
||||
FindClose(handle);
|
||||
return 0;
|
||||
#else
|
||||
struct dirent *entry;
|
||||
char buffer[1024 * 2];
|
||||
int length;
|
||||
DIR *d = opendir(dir);
|
||||
|
||||
if(!d)
|
||||
return 0;
|
||||
|
||||
str_format(buffer, sizeof(buffer), "%s/", dir);
|
||||
length = str_length(buffer);
|
||||
|
||||
while((entry = readdir(d)) != NULL)
|
||||
{
|
||||
str_copy(buffer + length, entry->d_name, (int)sizeof(buffer) - length);
|
||||
if(cb(entry->d_name, fs_getmtime(buffer), fs_is_dir(buffer), type, user))
|
||||
WideCharToMultiByte(CP_UTF8, 0, finddata.cFileName, -1, buffer2, IO_MAX_PATH_LENGTH, NULL, NULL);
|
||||
str_copy(buffer+length, buffer2, (int)sizeof(buffer)-length);
|
||||
if(cb(buffer2, fs_is_dir(buffer), type, user))
|
||||
break;
|
||||
}
|
||||
|
||||
/* close the directory and return */
|
||||
closedir(d);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
int fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user)
|
||||
{
|
||||
#if defined(CONF_FAMILY_WINDOWS)
|
||||
WIN32_FIND_DATA finddata;
|
||||
HANDLE handle;
|
||||
char buffer[1024 * 2];
|
||||
int length;
|
||||
str_format(buffer, sizeof(buffer), "%s/*", dir);
|
||||
|
||||
handle = FindFirstFileA(buffer, &finddata);
|
||||
|
||||
if(handle == INVALID_HANDLE_VALUE)
|
||||
return 0;
|
||||
|
||||
str_format(buffer, sizeof(buffer), "%s/", dir);
|
||||
length = str_length(buffer);
|
||||
|
||||
/* add all the entries */
|
||||
do
|
||||
{
|
||||
str_copy(buffer + length, finddata.cFileName, (int)sizeof(buffer) - length);
|
||||
if(cb(finddata.cFileName, fs_is_dir(buffer), type, user))
|
||||
break;
|
||||
} while(FindNextFileA(handle, &finddata));
|
||||
while(FindNextFileW(handle, &finddata));
|
||||
|
||||
FindClose(handle);
|
||||
return 0;
|
||||
#else
|
||||
struct dirent *entry;
|
||||
char buffer[1024 * 2];
|
||||
char buffer[IO_MAX_PATH_LENGTH];
|
||||
int length;
|
||||
DIR *d = opendir(dir);
|
||||
|
||||
if(!d)
|
||||
return 0;
|
||||
return;
|
||||
|
||||
str_format(buffer, sizeof(buffer), "%s/", dir);
|
||||
length = str_length(buffer);
|
||||
|
||||
while((entry = readdir(d)) != NULL)
|
||||
{
|
||||
str_copy(buffer + length, entry->d_name, (int)sizeof(buffer) - length);
|
||||
str_copy(buffer+length, entry->d_name, (int)sizeof(buffer)-length);
|
||||
if(cb(entry->d_name, fs_is_dir(buffer), type, user))
|
||||
break;
|
||||
}
|
||||
|
||||
/* close the directory and return */
|
||||
closedir(d);
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
void fs_listdir_fileinfo(const char *dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int type, void *user)
|
||||
{
|
||||
#if defined(CONF_FAMILY_WINDOWS)
|
||||
WIN32_FIND_DATAW finddata;
|
||||
HANDLE handle;
|
||||
char buffer[IO_MAX_PATH_LENGTH];
|
||||
char buffer2[IO_MAX_PATH_LENGTH];
|
||||
WCHAR wBuffer[IO_MAX_PATH_LENGTH];
|
||||
int length;
|
||||
|
||||
str_format(buffer, sizeof(buffer), "%s/*", dir);
|
||||
MultiByteToWideChar(CP_UTF8, 0, buffer, IO_MAX_PATH_LENGTH, wBuffer, IO_MAX_PATH_LENGTH);
|
||||
|
||||
handle = FindFirstFileW(wBuffer, &finddata);
|
||||
if(handle == INVALID_HANDLE_VALUE)
|
||||
return;
|
||||
|
||||
str_format(buffer, sizeof(buffer), "%s/", dir);
|
||||
length = str_length(buffer);
|
||||
|
||||
/* add all the entries */
|
||||
do
|
||||
{
|
||||
WideCharToMultiByte(CP_UTF8, 0, finddata.cFileName, -1, buffer2, IO_MAX_PATH_LENGTH, NULL, NULL);
|
||||
str_copy(buffer+length, buffer2, (int)sizeof(buffer)-length);
|
||||
|
||||
CFsFileInfo info;
|
||||
info.m_pName = buffer2;
|
||||
info.m_TimeCreated = filetime_to_unixtime(&finddata.ftCreationTime);
|
||||
info.m_TimeModified = filetime_to_unixtime(&finddata.ftLastWriteTime);
|
||||
|
||||
if(cb(&info, fs_is_dir(buffer), type, user))
|
||||
break;
|
||||
}
|
||||
while(FindNextFileW(handle, &finddata));
|
||||
|
||||
FindClose(handle);
|
||||
#else
|
||||
struct dirent *entry;
|
||||
time_t created = -1, modified = -1;
|
||||
char buffer[IO_MAX_PATH_LENGTH];
|
||||
int length;
|
||||
DIR *d = opendir(dir);
|
||||
|
||||
if(!d)
|
||||
return;
|
||||
|
||||
str_format(buffer, sizeof(buffer), "%s/", dir);
|
||||
length = str_length(buffer);
|
||||
|
||||
while((entry = readdir(d)) != NULL)
|
||||
{
|
||||
CFsFileInfo info;
|
||||
|
||||
str_copy(buffer+length, entry->d_name, (int)sizeof(buffer)-length);
|
||||
fs_file_time(buffer, &created, &modified);
|
||||
|
||||
info.m_pName = entry->d_name;
|
||||
info.m_TimeCreated = created;
|
||||
info.m_TimeModified = modified;
|
||||
|
||||
if(cb(&info, fs_is_dir(buffer), type, user))
|
||||
break;
|
||||
}
|
||||
|
||||
/* close the directory and return */
|
||||
closedir(d);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -174,7 +174,9 @@ enum
|
|||
|
||||
IOSEEK_START = 0,
|
||||
IOSEEK_CUR = 1,
|
||||
IOSEEK_END = 2
|
||||
IOSEEK_END = 2,
|
||||
|
||||
IO_MAX_PATH_LENGTH = 512,
|
||||
};
|
||||
|
||||
typedef struct IOINTERNAL *IOHANDLE;
|
||||
|
@ -1597,14 +1599,29 @@ void str_escape(char **dst, const char *src, const char *end);
|
|||
cb - Callback function to call for each entry
|
||||
type - Type of the directory
|
||||
user - Pointer to give to the callback
|
||||
|
||||
Returns:
|
||||
Always returns 0.
|
||||
*/
|
||||
typedef int (*FS_LISTDIR_CALLBACK)(const char *name, int is_dir, int dir_type, void *user);
|
||||
typedef int (*FS_LISTDIR_INFO_CALLBACK)(const char *name, time_t date, int is_dir, int dir_type, void *user);
|
||||
int fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user);
|
||||
int fs_listdir_info(const char *dir, FS_LISTDIR_INFO_CALLBACK cb, int type, void *user);
|
||||
void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const char *m_pName;
|
||||
time_t m_TimeCreated; // seconds since UNIX Epoch
|
||||
time_t m_TimeModified; // seconds since UNIX Epoch
|
||||
} CFsFileInfo;
|
||||
|
||||
/*
|
||||
Function: fs_listdir_fileinfo
|
||||
Lists the files in a directory and gets additional file information
|
||||
|
||||
Parameters:
|
||||
dir - Directory to list
|
||||
cb - Callback function to call for each entry
|
||||
type - Type of the directory
|
||||
user - Pointer to give to the callback
|
||||
*/
|
||||
typedef int (*FS_LISTDIR_CALLBACK_FILEINFO)(const CFsFileInfo *info, int is_dir, int dir_type, void *user);
|
||||
void fs_listdir_fileinfo(const char *dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int type, void *user);
|
||||
|
||||
/*
|
||||
Function: fs_makedir
|
||||
|
|
|
@ -300,19 +300,19 @@ public:
|
|||
// no binary directory found, use $PATH on Posix, $PWD on Windows
|
||||
}
|
||||
|
||||
virtual void ListDirectoryInfo(int Type, const char *pPath, FS_LISTDIR_INFO_CALLBACK pfnCallback, void *pUser)
|
||||
virtual void ListDirectoryInfo(int Type, const char *pPath, FS_LISTDIR_CALLBACK_FILEINFO pfnCallback, void *pUser)
|
||||
{
|
||||
char aBuffer[MAX_PATH_LENGTH];
|
||||
if(Type == TYPE_ALL)
|
||||
{
|
||||
// list all available directories
|
||||
for(int i = 0; i < m_NumPaths; ++i)
|
||||
fs_listdir_info(GetPath(i, pPath, aBuffer, sizeof(aBuffer)), pfnCallback, i, pUser);
|
||||
fs_listdir_fileinfo(GetPath(i, pPath, aBuffer, sizeof(aBuffer)), pfnCallback, i, pUser);
|
||||
}
|
||||
else if(Type >= 0 && Type < m_NumPaths)
|
||||
{
|
||||
// list wanted directory
|
||||
fs_listdir_info(GetPath(Type, pPath, aBuffer, sizeof(aBuffer)), pfnCallback, Type, pUser);
|
||||
fs_listdir_fileinfo(GetPath(Type, pPath, aBuffer, sizeof(aBuffer)), pfnCallback, Type, pUser);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ public:
|
|||
};
|
||||
|
||||
virtual void ListDirectory(int Type, const char *pPath, FS_LISTDIR_CALLBACK pfnCallback, void *pUser) = 0;
|
||||
virtual void ListDirectoryInfo(int Type, const char *pPath, FS_LISTDIR_INFO_CALLBACK pfnCallback, void *pUser) = 0;
|
||||
virtual void ListDirectoryInfo(int Type, const char *pPath, FS_LISTDIR_CALLBACK_FILEINFO pfnCallback, void *pUser) = 0;
|
||||
virtual IOHANDLE OpenFile(const char *pFilename, int Flags, int Type, char *pBuffer = 0, int BufferSize = 0) = 0;
|
||||
virtual bool FindFile(const char *pFilename, const char *pPath, int Type, char *pBuffer, int BufferSize) = 0;
|
||||
virtual bool RemoveFile(const char *pFilename, int Type) = 0;
|
||||
|
|
|
@ -442,7 +442,7 @@ protected:
|
|||
|
||||
void DemolistOnUpdate(bool Reset);
|
||||
//void DemolistPopulate();
|
||||
static int DemolistFetchCallback(const char *pName, time_t Date, int IsDir, int StorageType, void *pUser);
|
||||
static int DemolistFetchCallback(const CFsFileInfo *pInfo, int IsDir, int StorageType, void *pUser);
|
||||
|
||||
// friends
|
||||
struct CFriendItem
|
||||
|
|
|
@ -740,28 +740,28 @@ int CMenus::UiLogicGetCurrentClickedItem()
|
|||
return -1;
|
||||
}
|
||||
|
||||
int CMenus::DemolistFetchCallback(const char *pName, time_t Date, int IsDir, int StorageType, void *pUser)
|
||||
int CMenus::DemolistFetchCallback(const CFsFileInfo *pInfo, int IsDir, int StorageType, void *pUser)
|
||||
{
|
||||
CMenus *pSelf = (CMenus *)pUser;
|
||||
if(str_comp(pName, ".") == 0 || (str_comp(pName, "..") == 0 && str_comp(pSelf->m_aCurrentDemoFolder, "demos") == 0) || (!IsDir && !str_endswith(pName, ".demo")))
|
||||
if(str_comp(pInfo->m_pName, ".") == 0 || (str_comp(pInfo->m_pName, "..") == 0 && str_comp(pSelf->m_aCurrentDemoFolder, "demos") == 0) || (!IsDir && !str_endswith(pInfo->m_pName, ".demo")))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
CDemoItem Item;
|
||||
str_copy(Item.m_aFilename, pName, sizeof(Item.m_aFilename));
|
||||
str_copy(Item.m_aFilename, pInfo->m_pName, sizeof(Item.m_aFilename));
|
||||
if(IsDir)
|
||||
{
|
||||
str_format(Item.m_aName, sizeof(Item.m_aName), "%s/", pName);
|
||||
str_format(Item.m_aName, sizeof(Item.m_aName), "%s/", pInfo->m_pName);
|
||||
Item.m_InfosLoaded = false;
|
||||
Item.m_Valid = false;
|
||||
Item.m_Date = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
str_truncate(Item.m_aName, sizeof(Item.m_aName), pName, str_length(pName) - 5);
|
||||
str_truncate(Item.m_aName, sizeof(Item.m_aName), pInfo->m_pName, str_length(pInfo->m_pName) - 5);
|
||||
Item.m_InfosLoaded = false;
|
||||
Item.m_Date = Date;
|
||||
Item.m_Date = pInfo->m_TimeModified;
|
||||
}
|
||||
Item.m_IsDir = IsDir != 0;
|
||||
Item.m_StorageType = StorageType;
|
||||
|
|
|
@ -175,15 +175,15 @@ void CRaceDemo::StopRecord(int Time)
|
|||
m_RecordStopTick = -1;
|
||||
}
|
||||
|
||||
int CRaceDemo::RaceDemolistFetchCallback(const char *pName, time_t Date, int IsDir, int StorageType, void *pUser)
|
||||
int CRaceDemo::RaceDemolistFetchCallback(const CFsFileInfo *pInfo, int IsDir, int StorageType, void *pUser)
|
||||
{
|
||||
CDemoListParam *pParam = (CDemoListParam *)pUser;
|
||||
int MapLen = str_length(pParam->pMap);
|
||||
if(IsDir || !str_endswith(pName, ".demo") || !str_startswith(pName, pParam->pMap) || pName[MapLen] != '_')
|
||||
if(IsDir || !str_endswith(pInfo->m_pName, ".demo") || !str_startswith(pInfo->m_pName, pParam->pMap) || pInfo->m_pName[MapLen] != '_')
|
||||
return 0;
|
||||
|
||||
CDemoItem Item;
|
||||
str_truncate(Item.m_aName, sizeof(Item.m_aName), pName, str_length(pName) - 5);
|
||||
str_truncate(Item.m_aName, sizeof(Item.m_aName), pInfo->m_pName, str_length(pInfo->m_pName) - 5);
|
||||
|
||||
const char *pTime = Item.m_aName + MapLen + 1;
|
||||
const char *pTEnd = pTime;
|
||||
|
|
|
@ -25,7 +25,7 @@ class CRaceDemo : public CComponent
|
|||
int m_RecordStopTick;
|
||||
int m_Time;
|
||||
|
||||
static int RaceDemolistFetchCallback(const char *pName, time_t Date, int IsDir, int StorageType, void *pUser);
|
||||
static int RaceDemolistFetchCallback(const CFsFileInfo *pInfo, int IsDir, int StorageType, void *pUser);
|
||||
|
||||
void GetPath(char *pBuf, int Size, int Time = -1) const;
|
||||
|
||||
|
|
Loading…
Reference in a new issue