mirror of
https://github.com/ddnet/ddnet.git
synced 2024-11-13 03:28:19 +00:00
Merge #4377
4377: Fix incorrect/inconsistent buffer sizes, improve fs_is_dir, cleanup r=def- a=Robyt3 - Fix buffers sizes when using `MultiByteToWideChar` and `WideCharToMultiByte`. - input length is now always `-1`, as this will assume null-termination and also ensure it for the output - output length is the number of array elements (and not the size in bytes as previously specified in some cases) - Use `str_format` in `fs_storage_path` instead of platform specific functions for better maintainability. - Implement `fs_is_dir` smarter by using `GetFileAttributesW` on Windows. - Remove unused `fs_getmtime` that does not work with unicode on Windows in favor of the existing more generalized `fs_file_time`. ## Checklist - [x] Tested the change ingame - [ ] Provided screenshots if it is a visual change - [ ] Tested in combination with possibly related configuration options - [ ] Written a unit test if it works standalone, system.c especially - [ ] Considered possible null pointers and out of bounds array indexing - [ ] Changed no physics that affect existing maps - [ ] Tested the change with [ASan+UBSan or valgrind's memcheck](https://github.com/ddnet/ddnet/#using-addresssanitizer--undefinedbehavioursanitizer-or-valgrinds-memcheck) (optional) Co-authored-by: Robert Müller <robert.mueller@uni-siegen.de>
This commit is contained in:
commit
c18d4f8254
|
@ -164,7 +164,7 @@ static void logger_win_debugger(const char *line, void *user)
|
||||||
{
|
{
|
||||||
(void)user;
|
(void)user;
|
||||||
WCHAR wBuffer[512];
|
WCHAR wBuffer[512];
|
||||||
MultiByteToWideChar(CP_UTF8, 0, line, -1, wBuffer, sizeof(wBuffer));
|
MultiByteToWideChar(CP_UTF8, 0, line, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
|
||||||
OutputDebugStringW(wBuffer);
|
OutputDebugStringW(wBuffer);
|
||||||
OutputDebugStringW(L"\n");
|
OutputDebugStringW(L"\n");
|
||||||
}
|
}
|
||||||
|
@ -316,7 +316,7 @@ IOHANDLE io_open(const char *filename, int flags)
|
||||||
dbg_assert(flags == IOFLAG_READ || flags == IOFLAG_WRITE || flags == IOFLAG_APPEND, "flags must be read, write or append");
|
dbg_assert(flags == IOFLAG_READ || flags == IOFLAG_WRITE || flags == IOFLAG_APPEND, "flags must be read, write or append");
|
||||||
#if defined(CONF_FAMILY_WINDOWS)
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
WCHAR wBuffer[IO_MAX_PATH_LENGTH];
|
WCHAR wBuffer[IO_MAX_PATH_LENGTH];
|
||||||
MultiByteToWideChar(CP_UTF8, 0, filename, IO_MAX_PATH_LENGTH, wBuffer, IO_MAX_PATH_LENGTH);
|
MultiByteToWideChar(CP_UTF8, 0, filename, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
|
||||||
if(flags == IOFLAG_READ)
|
if(flags == IOFLAG_READ)
|
||||||
return (IOHANDLE)_wfsopen(wBuffer, L"rb", _SH_DENYNO);
|
return (IOHANDLE)_wfsopen(wBuffer, L"rb", _SH_DENYNO);
|
||||||
if(flags == IOFLAG_WRITE)
|
if(flags == IOFLAG_WRITE)
|
||||||
|
@ -1452,7 +1452,7 @@ static int priv_net_create_socket(int domain, int type, struct sockaddr *addr, i
|
||||||
int error = WSAGetLastError();
|
int error = WSAGetLastError();
|
||||||
if(FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, 0, wBuffer, sizeof(wBuffer) / sizeof(WCHAR), 0) == 0)
|
if(FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, 0, wBuffer, sizeof(wBuffer) / sizeof(WCHAR), 0) == 0)
|
||||||
wBuffer[0] = 0;
|
wBuffer[0] = 0;
|
||||||
WideCharToMultiByte(CP_UTF8, 0, wBuffer, sizeof(wBuffer), buf, sizeof(buf), NULL, NULL);
|
WideCharToMultiByte(CP_UTF8, 0, wBuffer, -1, buf, sizeof(buf), NULL, NULL);
|
||||||
dbg_msg("net", "failed to create socket with domain %d and type %d (%d '%s')", domain, type, error, buf);
|
dbg_msg("net", "failed to create socket with domain %d and type %d (%d '%s')", domain, type, error, buf);
|
||||||
#else
|
#else
|
||||||
dbg_msg("net", "failed to create socket with domain %d and type %d (%d '%s')", domain, type, errno, strerror(errno));
|
dbg_msg("net", "failed to create socket with domain %d and type %d (%d '%s')", domain, type, errno, strerror(errno));
|
||||||
|
@ -1491,7 +1491,7 @@ static int priv_net_create_socket(int domain, int type, struct sockaddr *addr, i
|
||||||
int error = WSAGetLastError();
|
int error = WSAGetLastError();
|
||||||
if(FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, 0, wBuffer, sizeof(wBuffer) / sizeof(WCHAR), 0) == 0)
|
if(FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, 0, error, 0, wBuffer, sizeof(wBuffer) / sizeof(WCHAR), 0) == 0)
|
||||||
wBuffer[0] = 0;
|
wBuffer[0] = 0;
|
||||||
WideCharToMultiByte(CP_UTF8, 0, wBuffer, sizeof(wBuffer), buf, sizeof(buf), NULL, NULL);
|
WideCharToMultiByte(CP_UTF8, 0, wBuffer, -1, buf, sizeof(buf), NULL, NULL);
|
||||||
dbg_msg("net", "failed to bind socket with domain %d and type %d (%d '%s')", domain, type, error, buf);
|
dbg_msg("net", "failed to bind socket with domain %d and type %d (%d '%s')", domain, type, error, buf);
|
||||||
#else
|
#else
|
||||||
dbg_msg("net", "failed to bind socket with domain %d and type %d (%d '%s')", domain, type, errno, strerror(errno));
|
dbg_msg("net", "failed to bind socket with domain %d and type %d (%d '%s')", domain, type, errno, strerror(errno));
|
||||||
|
@ -2060,7 +2060,7 @@ void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user)
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
str_format(buffer, sizeof(buffer), "%s/*", dir);
|
str_format(buffer, sizeof(buffer), "%s/*", dir);
|
||||||
MultiByteToWideChar(CP_UTF8, 0, buffer, IO_MAX_PATH_LENGTH, wBuffer, IO_MAX_PATH_LENGTH);
|
MultiByteToWideChar(CP_UTF8, 0, buffer, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
|
||||||
|
|
||||||
handle = FindFirstFileW(wBuffer, &finddata);
|
handle = FindFirstFileW(wBuffer, &finddata);
|
||||||
if(handle == INVALID_HANDLE_VALUE)
|
if(handle == INVALID_HANDLE_VALUE)
|
||||||
|
@ -2072,7 +2072,7 @@ void fs_listdir(const char *dir, FS_LISTDIR_CALLBACK cb, int type, void *user)
|
||||||
/* add all the entries */
|
/* add all the entries */
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
WideCharToMultiByte(CP_UTF8, 0, finddata.cFileName, -1, buffer2, IO_MAX_PATH_LENGTH, NULL, NULL);
|
WideCharToMultiByte(CP_UTF8, 0, finddata.cFileName, -1, buffer2, sizeof(buffer2), NULL, NULL);
|
||||||
str_copy(buffer + length, buffer2, (int)sizeof(buffer) - length);
|
str_copy(buffer + length, buffer2, (int)sizeof(buffer) - length);
|
||||||
if(cb(buffer2, fs_is_dir(buffer), type, user))
|
if(cb(buffer2, fs_is_dir(buffer), type, user))
|
||||||
break;
|
break;
|
||||||
|
@ -2114,7 +2114,7 @@ void fs_listdir_fileinfo(const char *dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int t
|
||||||
int length;
|
int length;
|
||||||
|
|
||||||
str_format(buffer, sizeof(buffer), "%s/*", dir);
|
str_format(buffer, sizeof(buffer), "%s/*", dir);
|
||||||
MultiByteToWideChar(CP_UTF8, 0, buffer, IO_MAX_PATH_LENGTH, wBuffer, IO_MAX_PATH_LENGTH);
|
MultiByteToWideChar(CP_UTF8, 0, buffer, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
|
||||||
|
|
||||||
handle = FindFirstFileW(wBuffer, &finddata);
|
handle = FindFirstFileW(wBuffer, &finddata);
|
||||||
if(handle == INVALID_HANDLE_VALUE)
|
if(handle == INVALID_HANDLE_VALUE)
|
||||||
|
@ -2126,7 +2126,7 @@ void fs_listdir_fileinfo(const char *dir, FS_LISTDIR_CALLBACK_FILEINFO cb, int t
|
||||||
/* add all the entries */
|
/* add all the entries */
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
WideCharToMultiByte(CP_UTF8, 0, finddata.cFileName, -1, buffer2, IO_MAX_PATH_LENGTH, NULL, NULL);
|
WideCharToMultiByte(CP_UTF8, 0, finddata.cFileName, -1, buffer2, sizeof(buffer2), NULL, NULL);
|
||||||
str_copy(buffer + length, buffer2, (int)sizeof(buffer) - length);
|
str_copy(buffer + length, buffer2, (int)sizeof(buffer) - length);
|
||||||
|
|
||||||
CFsFileInfo info;
|
CFsFileInfo info;
|
||||||
|
@ -2179,17 +2179,14 @@ int fs_storage_path(const char *appname, char *path, int max)
|
||||||
if(!home)
|
if(!home)
|
||||||
return -1;
|
return -1;
|
||||||
char buffer[IO_MAX_PATH_LENGTH];
|
char buffer[IO_MAX_PATH_LENGTH];
|
||||||
WideCharToMultiByte(CP_UTF8, 0, home, -1, buffer, IO_MAX_PATH_LENGTH, NULL, NULL);
|
WideCharToMultiByte(CP_UTF8, 0, home, -1, buffer, sizeof(buffer), NULL, NULL);
|
||||||
_snprintf(path, max, "%s/%s", buffer, appname);
|
str_format(path, max, "%s/%s", buffer, appname);
|
||||||
return 0;
|
return 0;
|
||||||
#elif defined(CONF_PLATFORM_ANDROID)
|
#elif defined(CONF_PLATFORM_ANDROID)
|
||||||
// just use the data directory
|
// just use the data directory
|
||||||
return -1;
|
return -1;
|
||||||
#else
|
#else
|
||||||
char *home = getenv("HOME");
|
char *home = getenv("HOME");
|
||||||
#if !defined(CONF_PLATFORM_MACOS)
|
|
||||||
int i;
|
|
||||||
#endif
|
|
||||||
if(!home)
|
if(!home)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
@ -2199,10 +2196,10 @@ int fs_storage_path(const char *appname, char *path, int max)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(CONF_PLATFORM_MACOS)
|
#if defined(CONF_PLATFORM_MACOS)
|
||||||
snprintf(path, max, "%s/Library/Application Support/%s", home, appname);
|
str_format(path, max, "%s/Library/Application Support/%s", home, appname);
|
||||||
#else
|
#else
|
||||||
snprintf(path, max, "%s/.%s", home, appname);
|
str_format(path, max, "%s/.%s", home, appname);
|
||||||
for(i = str_length(home) + 2; path[i]; i++)
|
for(int i = str_length(home) + 2; path[i]; i++)
|
||||||
path[i] = tolower((unsigned char)path[i]);
|
path[i] = tolower((unsigned char)path[i]);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -2232,7 +2229,7 @@ int fs_makedir(const char *path)
|
||||||
{
|
{
|
||||||
#if defined(CONF_FAMILY_WINDOWS)
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
WCHAR wBuffer[IO_MAX_PATH_LENGTH];
|
WCHAR wBuffer[IO_MAX_PATH_LENGTH];
|
||||||
MultiByteToWideChar(CP_UTF8, 0, path, -1, wBuffer, IO_MAX_PATH_LENGTH);
|
MultiByteToWideChar(CP_UTF8, 0, path, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
|
||||||
if(_wmkdir(wBuffer) == 0)
|
if(_wmkdir(wBuffer) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
if(errno == EEXIST)
|
if(errno == EEXIST)
|
||||||
|
@ -2256,7 +2253,7 @@ int fs_removedir(const char *path)
|
||||||
{
|
{
|
||||||
#if defined(CONF_FAMILY_WINDOWS)
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
WCHAR wPath[IO_MAX_PATH_LENGTH];
|
WCHAR wPath[IO_MAX_PATH_LENGTH];
|
||||||
MultiByteToWideChar(CP_UTF8, 0, path, IO_MAX_PATH_LENGTH, wPath, IO_MAX_PATH_LENGTH);
|
MultiByteToWideChar(CP_UTF8, 0, path, -1, wPath, sizeof(wPath) / sizeof(WCHAR));
|
||||||
if(RemoveDirectoryW(wPath) != 0)
|
if(RemoveDirectoryW(wPath) != 0)
|
||||||
return 0;
|
return 0;
|
||||||
return -1;
|
return -1;
|
||||||
|
@ -2270,18 +2267,10 @@ int fs_removedir(const char *path)
|
||||||
int fs_is_dir(const char *path)
|
int fs_is_dir(const char *path)
|
||||||
{
|
{
|
||||||
#if defined(CONF_FAMILY_WINDOWS)
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
/* TODO: do this smarter */
|
WCHAR wPath[IO_MAX_PATH_LENGTH];
|
||||||
WIN32_FIND_DATAW finddata;
|
MultiByteToWideChar(CP_UTF8, 0, path, -1, wPath, sizeof(wPath) / sizeof(WCHAR));
|
||||||
HANDLE handle;
|
DWORD attributes = GetFileAttributesW(wPath);
|
||||||
char buffer[IO_MAX_PATH_LENGTH];
|
return attributes != INVALID_FILE_ATTRIBUTES && (attributes & FILE_ATTRIBUTE_DIRECTORY) ? 1 : 0;
|
||||||
WCHAR wBuffer[IO_MAX_PATH_LENGTH];
|
|
||||||
str_format(buffer, sizeof(buffer), "%s/*", path);
|
|
||||||
MultiByteToWideChar(CP_UTF8, 0, buffer, IO_MAX_PATH_LENGTH, wBuffer, IO_MAX_PATH_LENGTH);
|
|
||||||
|
|
||||||
if((handle = FindFirstFileW(wBuffer, &finddata)) == INVALID_HANDLE_VALUE)
|
|
||||||
return 0;
|
|
||||||
FindClose(handle);
|
|
||||||
return 1;
|
|
||||||
#else
|
#else
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
if(stat(path, &sb) == -1)
|
if(stat(path, &sb) == -1)
|
||||||
|
@ -2290,22 +2279,13 @@ int fs_is_dir(const char *path)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
time_t fs_getmtime(const char *path)
|
|
||||||
{
|
|
||||||
struct stat sb;
|
|
||||||
if(stat(path, &sb) == -1)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
return sb.st_mtime;
|
|
||||||
}
|
|
||||||
|
|
||||||
int fs_chdir(const char *path)
|
int fs_chdir(const char *path)
|
||||||
{
|
{
|
||||||
if(fs_is_dir(path))
|
if(fs_is_dir(path))
|
||||||
{
|
{
|
||||||
#if defined(CONF_FAMILY_WINDOWS)
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
WCHAR wBuffer[IO_MAX_PATH_LENGTH];
|
WCHAR wBuffer[IO_MAX_PATH_LENGTH];
|
||||||
MultiByteToWideChar(CP_UTF8, 0, path, -1, wBuffer, IO_MAX_PATH_LENGTH);
|
MultiByteToWideChar(CP_UTF8, 0, path, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
|
||||||
if(_wchdir(wBuffer))
|
if(_wchdir(wBuffer))
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
|
@ -2329,7 +2309,7 @@ char *fs_getcwd(char *buffer, int buffer_size)
|
||||||
WCHAR wBuffer[IO_MAX_PATH_LENGTH];
|
WCHAR wBuffer[IO_MAX_PATH_LENGTH];
|
||||||
if(_wgetcwd(wBuffer, buffer_size) == 0)
|
if(_wgetcwd(wBuffer, buffer_size) == 0)
|
||||||
return 0;
|
return 0;
|
||||||
WideCharToMultiByte(CP_UTF8, 0, wBuffer, IO_MAX_PATH_LENGTH, buffer, buffer_size, NULL, NULL);
|
WideCharToMultiByte(CP_UTF8, 0, wBuffer, -1, buffer, buffer_size, NULL, NULL);
|
||||||
return buffer;
|
return buffer;
|
||||||
#else
|
#else
|
||||||
return getcwd(buffer, buffer_size);
|
return getcwd(buffer, buffer_size);
|
||||||
|
@ -2357,7 +2337,7 @@ int fs_remove(const char *filename)
|
||||||
{
|
{
|
||||||
#if defined(CONF_FAMILY_WINDOWS)
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
WCHAR wFilename[IO_MAX_PATH_LENGTH];
|
WCHAR wFilename[IO_MAX_PATH_LENGTH];
|
||||||
MultiByteToWideChar(CP_UTF8, 0, filename, IO_MAX_PATH_LENGTH, wFilename, IO_MAX_PATH_LENGTH);
|
MultiByteToWideChar(CP_UTF8, 0, filename, -1, wFilename, sizeof(wFilename) / sizeof(WCHAR));
|
||||||
return DeleteFileW(wFilename) == 0;
|
return DeleteFileW(wFilename) == 0;
|
||||||
#else
|
#else
|
||||||
return unlink(filename) != 0;
|
return unlink(filename) != 0;
|
||||||
|
@ -2369,8 +2349,8 @@ int fs_rename(const char *oldname, const char *newname)
|
||||||
#if defined(CONF_FAMILY_WINDOWS)
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
WCHAR wOldname[IO_MAX_PATH_LENGTH];
|
WCHAR wOldname[IO_MAX_PATH_LENGTH];
|
||||||
WCHAR wNewname[IO_MAX_PATH_LENGTH];
|
WCHAR wNewname[IO_MAX_PATH_LENGTH];
|
||||||
MultiByteToWideChar(CP_UTF8, 0, oldname, IO_MAX_PATH_LENGTH, wOldname, IO_MAX_PATH_LENGTH);
|
MultiByteToWideChar(CP_UTF8, 0, oldname, -1, wOldname, sizeof(wOldname) / sizeof(WCHAR));
|
||||||
MultiByteToWideChar(CP_UTF8, 0, newname, IO_MAX_PATH_LENGTH, wNewname, IO_MAX_PATH_LENGTH);
|
MultiByteToWideChar(CP_UTF8, 0, newname, -1, wNewname, sizeof(wNewname) / sizeof(WCHAR));
|
||||||
if(MoveFileExW(wOldname, wNewname, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) == 0)
|
if(MoveFileExW(wOldname, wNewname, MOVEFILE_REPLACE_EXISTING | MOVEFILE_COPY_ALLOWED) == 0)
|
||||||
return 1;
|
return 1;
|
||||||
#else
|
#else
|
||||||
|
@ -2387,7 +2367,7 @@ int fs_file_time(const char *name, time_t *created, time_t *modified)
|
||||||
HANDLE handle;
|
HANDLE handle;
|
||||||
WCHAR wBuffer[IO_MAX_PATH_LENGTH];
|
WCHAR wBuffer[IO_MAX_PATH_LENGTH];
|
||||||
|
|
||||||
MultiByteToWideChar(CP_UTF8, 0, name, IO_MAX_PATH_LENGTH, wBuffer, IO_MAX_PATH_LENGTH);
|
MultiByteToWideChar(CP_UTF8, 0, name, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
|
||||||
handle = FindFirstFileW(wBuffer, &finddata);
|
handle = FindFirstFileW(wBuffer, &finddata);
|
||||||
if(handle == INVALID_HANDLE_VALUE)
|
if(handle == INVALID_HANDLE_VALUE)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -3566,7 +3546,7 @@ PROCESS shell_execute(const char *file)
|
||||||
{
|
{
|
||||||
#if defined(CONF_FAMILY_WINDOWS)
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
WCHAR wBuffer[512];
|
WCHAR wBuffer[512];
|
||||||
MultiByteToWideChar(CP_UTF8, 0, file, -1, wBuffer, sizeof(wBuffer));
|
MultiByteToWideChar(CP_UTF8, 0, file, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
|
||||||
SHELLEXECUTEINFOW info;
|
SHELLEXECUTEINFOW info;
|
||||||
mem_zero(&info, sizeof(SHELLEXECUTEINFOW));
|
mem_zero(&info, sizeof(SHELLEXECUTEINFOW));
|
||||||
info.cbSize = sizeof(SHELLEXECUTEINFOW);
|
info.cbSize = sizeof(SHELLEXECUTEINFOW);
|
||||||
|
@ -3610,7 +3590,7 @@ int open_link(const char *link)
|
||||||
{
|
{
|
||||||
#if defined(CONF_FAMILY_WINDOWS)
|
#if defined(CONF_FAMILY_WINDOWS)
|
||||||
WCHAR wBuffer[512];
|
WCHAR wBuffer[512];
|
||||||
MultiByteToWideChar(CP_UTF8, 0, link, -1, wBuffer, sizeof(wBuffer));
|
MultiByteToWideChar(CP_UTF8, 0, link, -1, wBuffer, sizeof(wBuffer) / sizeof(WCHAR));
|
||||||
return (uintptr_t)ShellExecuteW(NULL, L"open", wBuffer, NULL, NULL, SW_SHOWDEFAULT) > 32;
|
return (uintptr_t)ShellExecuteW(NULL, L"open", wBuffer, NULL, NULL, SW_SHOWDEFAULT) > 32;
|
||||||
#elif defined(CONF_PLATFORM_LINUX)
|
#elif defined(CONF_PLATFORM_LINUX)
|
||||||
char aBuf[512];
|
char aBuf[512];
|
||||||
|
|
|
@ -1689,12 +1689,6 @@ int fs_storage_path(const char *appname, char *path, int max);
|
||||||
*/
|
*/
|
||||||
int fs_is_dir(const char *path);
|
int fs_is_dir(const char *path);
|
||||||
|
|
||||||
/*
|
|
||||||
Function: fs_getmtime
|
|
||||||
Gets the modification time of a file
|
|
||||||
*/
|
|
||||||
time_t fs_getmtime(const char *path);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Function: fs_chdir
|
Function: fs_chdir
|
||||||
Changes current working directory
|
Changes current working directory
|
||||||
|
|
Loading…
Reference in a new issue