mirror of
https://github.com/thunderbrewhq/thunderbrew
synced 2025-12-14 20:12:29 +00:00
chore(build): use SDL3
This commit is contained in:
parent
9d04a35d87
commit
b3c0734a9e
3286 changed files with 866354 additions and 554996 deletions
530
vendor/sdl-3.2.10/src/filesystem/SDL_filesystem.c
vendored
Normal file
530
vendor/sdl-3.2.10/src/filesystem/SDL_filesystem.c
vendored
Normal file
|
|
@ -0,0 +1,530 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#include "SDL_filesystem_c.h"
|
||||
#include "SDL_sysfilesystem.h"
|
||||
#include "../stdlib/SDL_sysstdlib.h"
|
||||
|
||||
bool SDL_RemovePath(const char *path)
|
||||
{
|
||||
if (!path) {
|
||||
return SDL_InvalidParamError("path");
|
||||
}
|
||||
return SDL_SYS_RemovePath(path);
|
||||
}
|
||||
|
||||
bool SDL_RenamePath(const char *oldpath, const char *newpath)
|
||||
{
|
||||
if (!oldpath) {
|
||||
return SDL_InvalidParamError("oldpath");
|
||||
} else if (!newpath) {
|
||||
return SDL_InvalidParamError("newpath");
|
||||
}
|
||||
return SDL_SYS_RenamePath(oldpath, newpath);
|
||||
}
|
||||
|
||||
bool SDL_CopyFile(const char *oldpath, const char *newpath)
|
||||
{
|
||||
if (!oldpath) {
|
||||
return SDL_InvalidParamError("oldpath");
|
||||
} else if (!newpath) {
|
||||
return SDL_InvalidParamError("newpath");
|
||||
}
|
||||
return SDL_SYS_CopyFile(oldpath, newpath);
|
||||
}
|
||||
|
||||
bool SDL_CreateDirectory(const char *path)
|
||||
{
|
||||
if (!path) {
|
||||
return SDL_InvalidParamError("path");
|
||||
}
|
||||
|
||||
bool retval = SDL_SYS_CreateDirectory(path);
|
||||
if (!retval && *path) { // maybe we're missing parent directories?
|
||||
char *parents = SDL_strdup(path);
|
||||
if (!parents) {
|
||||
return false; // oh well.
|
||||
}
|
||||
|
||||
// in case there was a separator at the end of the path and it was
|
||||
// upsetting something, chop it off.
|
||||
const size_t slen = SDL_strlen(parents);
|
||||
#ifdef SDL_PLATFORM_WINDOWS
|
||||
if ((parents[slen - 1] == '/') || (parents[slen - 1] == '\\'))
|
||||
#else
|
||||
if (parents[slen - 1] == '/')
|
||||
#endif
|
||||
{
|
||||
parents[slen - 1] = '\0';
|
||||
retval = SDL_SYS_CreateDirectory(parents);
|
||||
}
|
||||
|
||||
if (!retval) {
|
||||
for (char *ptr = parents; *ptr; ptr++) {
|
||||
const char ch = *ptr;
|
||||
#ifdef SDL_PLATFORM_WINDOWS
|
||||
const bool issep = (ch == '/') || (ch == '\\');
|
||||
if (issep && ((ptr - parents) == 2) && (parents[1] == ':')) {
|
||||
continue; // it's just the drive letter, skip it.
|
||||
}
|
||||
#else
|
||||
const bool issep = (ch == '/');
|
||||
if (issep && ((ptr - parents) == 0)) {
|
||||
continue; // it's just the root directory, skip it.
|
||||
}
|
||||
#endif
|
||||
|
||||
if (issep) {
|
||||
*ptr = '\0';
|
||||
// (this does not fail if the path already exists as a directory.)
|
||||
retval = SDL_SYS_CreateDirectory(parents);
|
||||
if (!retval) { // still failing when making parents? Give up.
|
||||
break;
|
||||
}
|
||||
*ptr = ch;
|
||||
}
|
||||
}
|
||||
|
||||
// last chance: did it work this time?
|
||||
retval = SDL_SYS_CreateDirectory(parents);
|
||||
}
|
||||
|
||||
SDL_free(parents);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
||||
bool SDL_EnumerateDirectory(const char *path, SDL_EnumerateDirectoryCallback callback, void *userdata)
|
||||
{
|
||||
if (!path) {
|
||||
return SDL_InvalidParamError("path");
|
||||
} else if (!callback) {
|
||||
return SDL_InvalidParamError("callback");
|
||||
}
|
||||
return SDL_SYS_EnumerateDirectory(path, callback, userdata);
|
||||
}
|
||||
|
||||
bool SDL_GetPathInfo(const char *path, SDL_PathInfo *info)
|
||||
{
|
||||
SDL_PathInfo dummy;
|
||||
|
||||
if (!info) {
|
||||
info = &dummy;
|
||||
}
|
||||
SDL_zerop(info);
|
||||
|
||||
if (!path) {
|
||||
return SDL_InvalidParamError("path");
|
||||
}
|
||||
|
||||
return SDL_SYS_GetPathInfo(path, info);
|
||||
}
|
||||
|
||||
static bool EverythingMatch(const char *pattern, const char *str, bool *matched_to_dir)
|
||||
{
|
||||
SDL_assert(pattern == NULL);
|
||||
SDL_assert(str != NULL);
|
||||
SDL_assert(matched_to_dir != NULL);
|
||||
|
||||
*matched_to_dir = true;
|
||||
return true; // everything matches!
|
||||
}
|
||||
|
||||
// this is just '*' and '?', with '/' matching nothing.
|
||||
static bool WildcardMatch(const char *pattern, const char *str, bool *matched_to_dir)
|
||||
{
|
||||
SDL_assert(pattern != NULL);
|
||||
SDL_assert(str != NULL);
|
||||
SDL_assert(matched_to_dir != NULL);
|
||||
|
||||
const char *str_backtrack = NULL;
|
||||
const char *pattern_backtrack = NULL;
|
||||
char sch_backtrack = 0;
|
||||
char sch = *str;
|
||||
char pch = *pattern;
|
||||
|
||||
while (sch) {
|
||||
if (pch == '*') {
|
||||
str_backtrack = str;
|
||||
pattern_backtrack = ++pattern;
|
||||
sch_backtrack = sch;
|
||||
pch = *pattern;
|
||||
} else if (pch == sch) {
|
||||
if (pch == '/') {
|
||||
str_backtrack = pattern_backtrack = NULL;
|
||||
}
|
||||
sch = *(++str);
|
||||
pch = *(++pattern);
|
||||
} else if ((pch == '?') && (sch != '/')) { // end of string (checked at `while`) or path separator do not match '?'.
|
||||
sch = *(++str);
|
||||
pch = *(++pattern);
|
||||
} else if (!pattern_backtrack || (sch_backtrack == '/')) { // we didn't have a match. Are we in a '*' and NOT on a path separator? Keep going. Otherwise, fail.
|
||||
*matched_to_dir = false;
|
||||
return false;
|
||||
} else { // still here? Wasn't a match, but we're definitely in a '*' pattern.
|
||||
str = ++str_backtrack;
|
||||
pattern = pattern_backtrack;
|
||||
sch_backtrack = sch;
|
||||
sch = *str;
|
||||
pch = *pattern;
|
||||
}
|
||||
|
||||
#ifdef SDL_PLATFORM_WINDOWS
|
||||
if (sch == '\\') {
|
||||
sch = '/';
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
// '*' at the end can be ignored, they are allowed to match nothing.
|
||||
while (pch == '*') {
|
||||
pch = *(++pattern);
|
||||
}
|
||||
|
||||
*matched_to_dir = ((pch == '/') || (pch == '\0')); // end of string and the pattern is complete or failed at a '/'? We should descend into this directory.
|
||||
|
||||
return (pch == '\0'); // survived the whole pattern? That's a match!
|
||||
}
|
||||
|
||||
|
||||
// Note that this will currently encode illegal codepoints: UTF-16 surrogates, 0xFFFE, and 0xFFFF.
|
||||
// and a codepoint > 0x10FFFF will fail the same as if there wasn't enough memory.
|
||||
// clean this up if you want to move this to SDL_string.c.
|
||||
static size_t EncodeCodepointToUtf8(char *ptr, Uint32 cp, size_t remaining)
|
||||
{
|
||||
if (cp < 0x80) { // fits in a single UTF-8 byte.
|
||||
if (remaining) {
|
||||
*ptr = (char) cp;
|
||||
return 1;
|
||||
}
|
||||
} else if (cp < 0x800) { // fits in 2 bytes.
|
||||
if (remaining >= 2) {
|
||||
ptr[0] = (char) ((cp >> 6) | 128 | 64);
|
||||
ptr[1] = (char) (cp & 0x3F) | 128;
|
||||
return 2;
|
||||
}
|
||||
} else if (cp < 0x10000) { // fits in 3 bytes.
|
||||
if (remaining >= 3) {
|
||||
ptr[0] = (char) ((cp >> 12) | 128 | 64 | 32);
|
||||
ptr[1] = (char) ((cp >> 6) & 0x3F) | 128;
|
||||
ptr[2] = (char) (cp & 0x3F) | 128;
|
||||
return 3;
|
||||
}
|
||||
} else if (cp <= 0x10FFFF) { // fits in 4 bytes.
|
||||
if (remaining >= 4) {
|
||||
ptr[0] = (char) ((cp >> 18) | 128 | 64 | 32 | 16);
|
||||
ptr[1] = (char) ((cp >> 12) & 0x3F) | 128;
|
||||
ptr[2] = (char) ((cp >> 6) & 0x3F) | 128;
|
||||
ptr[3] = (char) (cp & 0x3F) | 128;
|
||||
return 4;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static char *CaseFoldUtf8String(const char *fname)
|
||||
{
|
||||
SDL_assert(fname != NULL);
|
||||
const size_t allocation = (SDL_strlen(fname) + 1) * 3 * 4;
|
||||
char *result = (char *) SDL_malloc(allocation); // lazy: just allocating the max needed.
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
Uint32 codepoint;
|
||||
char *ptr = result;
|
||||
size_t remaining = allocation;
|
||||
while ((codepoint = SDL_StepUTF8(&fname, NULL)) != 0) {
|
||||
Uint32 folded[3];
|
||||
const int num_folded = SDL_CaseFoldUnicode(codepoint, folded);
|
||||
SDL_assert(num_folded > 0);
|
||||
SDL_assert(num_folded <= SDL_arraysize(folded));
|
||||
for (int i = 0; i < num_folded; i++) {
|
||||
SDL_assert(remaining > 0);
|
||||
const size_t rc = EncodeCodepointToUtf8(ptr, folded[i], remaining);
|
||||
SDL_assert(rc > 0);
|
||||
SDL_assert(rc < remaining);
|
||||
remaining -= rc;
|
||||
ptr += rc;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(remaining > 0);
|
||||
remaining--;
|
||||
*ptr = '\0';
|
||||
|
||||
if (remaining > 0) {
|
||||
SDL_assert(allocation > remaining);
|
||||
ptr = (char *)SDL_realloc(result, allocation - remaining); // shrink it down.
|
||||
if (ptr) { // shouldn't fail, but if it does, `result` is still valid.
|
||||
result = ptr;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
typedef struct GlobDirCallbackData
|
||||
{
|
||||
bool (*matcher)(const char *pattern, const char *str, bool *matched_to_dir);
|
||||
const char *pattern;
|
||||
int num_entries;
|
||||
SDL_GlobFlags flags;
|
||||
SDL_GlobEnumeratorFunc enumerator;
|
||||
SDL_GlobGetPathInfoFunc getpathinfo;
|
||||
void *fsuserdata;
|
||||
size_t basedirlen;
|
||||
SDL_IOStream *string_stream;
|
||||
} GlobDirCallbackData;
|
||||
|
||||
static SDL_EnumerationResult SDLCALL GlobDirectoryCallback(void *userdata, const char *dirname, const char *fname)
|
||||
{
|
||||
SDL_assert(userdata != NULL);
|
||||
SDL_assert(dirname != NULL);
|
||||
SDL_assert(fname != NULL);
|
||||
|
||||
//SDL_Log("GlobDirectoryCallback('%s', '%s')", dirname, fname);
|
||||
|
||||
GlobDirCallbackData *data = (GlobDirCallbackData *) userdata;
|
||||
|
||||
// !!! FIXME: if we're careful, we can keep a single buffer in `data` that we push and pop paths off the end of as we walk the tree,
|
||||
// !!! FIXME: and only casefold the new pieces instead of allocating and folding full paths for all of this.
|
||||
|
||||
char *fullpath = NULL;
|
||||
if (SDL_asprintf(&fullpath, "%s%s", dirname, fname) < 0) {
|
||||
return SDL_ENUM_FAILURE;
|
||||
}
|
||||
|
||||
char *folded = NULL;
|
||||
if (data->flags & SDL_GLOB_CASEINSENSITIVE) {
|
||||
folded = CaseFoldUtf8String(fullpath);
|
||||
if (!folded) {
|
||||
return SDL_ENUM_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
bool matched_to_dir = false;
|
||||
const bool matched = data->matcher(data->pattern, (folded ? folded : fullpath) + data->basedirlen, &matched_to_dir);
|
||||
//SDL_Log("GlobDirectoryCallback: Considered %spath='%s' vs pattern='%s': %smatched (matched_to_dir=%s)", folded ? "(folded) " : "", (folded ? folded : fullpath) + data->basedirlen, data->pattern, matched ? "" : "NOT ", matched_to_dir ? "TRUE" : "FALSE");
|
||||
SDL_free(folded);
|
||||
|
||||
if (matched) {
|
||||
const char *subpath = fullpath + data->basedirlen;
|
||||
const size_t slen = SDL_strlen(subpath) + 1;
|
||||
if (SDL_WriteIO(data->string_stream, subpath, slen) != slen) {
|
||||
SDL_free(fullpath);
|
||||
return SDL_ENUM_FAILURE; // stop enumerating, return failure to the app.
|
||||
}
|
||||
data->num_entries++;
|
||||
}
|
||||
|
||||
SDL_EnumerationResult result = SDL_ENUM_CONTINUE; // keep enumerating by default.
|
||||
if (matched_to_dir) {
|
||||
SDL_PathInfo info;
|
||||
if (data->getpathinfo(fullpath, &info, data->fsuserdata) && (info.type == SDL_PATHTYPE_DIRECTORY)) {
|
||||
//SDL_Log("GlobDirectoryCallback: Descending into subdir '%s'", fname);
|
||||
if (!data->enumerator(fullpath, GlobDirectoryCallback, data, data->fsuserdata)) {
|
||||
result = SDL_ENUM_FAILURE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_free(fullpath);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char **SDL_InternalGlobDirectory(const char *path, const char *pattern, SDL_GlobFlags flags, int *count, SDL_GlobEnumeratorFunc enumerator, SDL_GlobGetPathInfoFunc getpathinfo, void *userdata)
|
||||
{
|
||||
int dummycount;
|
||||
if (!count) {
|
||||
count = &dummycount;
|
||||
}
|
||||
*count = 0;
|
||||
|
||||
if (!path) {
|
||||
SDL_InvalidParamError("path");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// if path ends with any slash, chop them off, so we don't confuse the pattern matcher later.
|
||||
char *pathcpy = NULL;
|
||||
size_t pathlen = SDL_strlen(path);
|
||||
if ((pathlen > 1) && ((path[pathlen-1] == '/') || (path[pathlen-1] == '\\'))) {
|
||||
pathcpy = SDL_strdup(path);
|
||||
if (!pathcpy) {
|
||||
return NULL;
|
||||
}
|
||||
char *ptr = &pathcpy[pathlen-1];
|
||||
while ((ptr >= pathcpy) && ((*ptr == '/') || (*ptr == '\\'))) {
|
||||
*(ptr--) = '\0';
|
||||
}
|
||||
path = pathcpy;
|
||||
}
|
||||
|
||||
if (!pattern) {
|
||||
flags &= ~SDL_GLOB_CASEINSENSITIVE; // avoid some unnecessary allocations and work later.
|
||||
}
|
||||
|
||||
char *folded = NULL;
|
||||
if (flags & SDL_GLOB_CASEINSENSITIVE) {
|
||||
SDL_assert(pattern != NULL);
|
||||
folded = CaseFoldUtf8String(pattern);
|
||||
if (!folded) {
|
||||
SDL_free(pathcpy);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
GlobDirCallbackData data;
|
||||
SDL_zero(data);
|
||||
data.string_stream = SDL_IOFromDynamicMem();
|
||||
if (!data.string_stream) {
|
||||
SDL_free(folded);
|
||||
SDL_free(pathcpy);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!pattern) {
|
||||
data.matcher = EverythingMatch; // no pattern? Everything matches.
|
||||
|
||||
// !!! FIXME
|
||||
//} else if (flags & SDL_GLOB_GITIGNORE) {
|
||||
// data.matcher = GitIgnoreMatch;
|
||||
|
||||
} else {
|
||||
data.matcher = WildcardMatch;
|
||||
}
|
||||
|
||||
data.pattern = folded ? folded : pattern;
|
||||
data.flags = flags;
|
||||
data.enumerator = enumerator;
|
||||
data.getpathinfo = getpathinfo;
|
||||
data.fsuserdata = userdata;
|
||||
data.basedirlen = *path ? (SDL_strlen(path) + 1) : 0; // +1 for the '/' we'll be adding.
|
||||
|
||||
|
||||
char **result = NULL;
|
||||
if (data.enumerator(path, GlobDirectoryCallback, &data, data.fsuserdata)) {
|
||||
const size_t streamlen = (size_t) SDL_GetIOSize(data.string_stream);
|
||||
const size_t buflen = streamlen + ((data.num_entries + 1) * sizeof (char *)); // +1 for NULL terminator at end of array.
|
||||
result = (char **) SDL_malloc(buflen);
|
||||
if (result) {
|
||||
if (data.num_entries > 0) {
|
||||
Sint64 iorc = SDL_SeekIO(data.string_stream, 0, SDL_IO_SEEK_SET);
|
||||
SDL_assert(iorc == 0); // this should never fail for a memory stream!
|
||||
char *ptr = (char *) (result + (data.num_entries + 1));
|
||||
iorc = SDL_ReadIO(data.string_stream, ptr, streamlen);
|
||||
SDL_assert(iorc == (Sint64) streamlen); // this should never fail for a memory stream!
|
||||
for (int i = 0; i < data.num_entries; i++) {
|
||||
result[i] = ptr;
|
||||
ptr += SDL_strlen(ptr) + 1;
|
||||
}
|
||||
}
|
||||
result[data.num_entries] = NULL; // NULL terminate the list.
|
||||
*count = data.num_entries;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_CloseIO(data.string_stream);
|
||||
SDL_free(folded);
|
||||
SDL_free(pathcpy);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool GlobDirectoryGetPathInfo(const char *path, SDL_PathInfo *info, void *userdata)
|
||||
{
|
||||
return SDL_GetPathInfo(path, info);
|
||||
}
|
||||
|
||||
static bool GlobDirectoryEnumerator(const char *path, SDL_EnumerateDirectoryCallback cb, void *cbuserdata, void *userdata)
|
||||
{
|
||||
return SDL_EnumerateDirectory(path, cb, cbuserdata);
|
||||
}
|
||||
|
||||
char **SDL_GlobDirectory(const char *path, const char *pattern, SDL_GlobFlags flags, int *count)
|
||||
{
|
||||
//SDL_Log("SDL_GlobDirectory('%s', '%s') ...", path, pattern);
|
||||
return SDL_InternalGlobDirectory(path, pattern, flags, count, GlobDirectoryEnumerator, GlobDirectoryGetPathInfo, NULL);
|
||||
}
|
||||
|
||||
|
||||
static char *CachedBasePath = NULL;
|
||||
|
||||
const char *SDL_GetBasePath(void)
|
||||
{
|
||||
if (!CachedBasePath) {
|
||||
CachedBasePath = SDL_SYS_GetBasePath();
|
||||
}
|
||||
return CachedBasePath;
|
||||
}
|
||||
|
||||
|
||||
static char *CachedUserFolders[SDL_FOLDER_COUNT];
|
||||
|
||||
const char *SDL_GetUserFolder(SDL_Folder folder)
|
||||
{
|
||||
const int idx = (int) folder;
|
||||
if ((idx < 0) || (idx >= SDL_arraysize(CachedUserFolders))) {
|
||||
SDL_InvalidParamError("folder");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!CachedUserFolders[idx]) {
|
||||
CachedUserFolders[idx] = SDL_SYS_GetUserFolder(folder);
|
||||
}
|
||||
return CachedUserFolders[idx];
|
||||
}
|
||||
|
||||
|
||||
char *SDL_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
return SDL_SYS_GetPrefPath(org, app);
|
||||
}
|
||||
|
||||
char *SDL_GetCurrentDirectory(void)
|
||||
{
|
||||
return SDL_SYS_GetCurrentDirectory();
|
||||
}
|
||||
|
||||
void SDL_InitFilesystem(void)
|
||||
{
|
||||
}
|
||||
|
||||
void SDL_QuitFilesystem(void)
|
||||
{
|
||||
if (CachedBasePath) {
|
||||
SDL_free(CachedBasePath);
|
||||
CachedBasePath = NULL;
|
||||
}
|
||||
for (int i = 0; i < SDL_arraysize(CachedUserFolders); i++) {
|
||||
if (CachedUserFolders[i]) {
|
||||
SDL_free(CachedUserFolders[i]);
|
||||
CachedUserFolders[i] = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
29
vendor/sdl-3.2.10/src/filesystem/SDL_filesystem_c.h
vendored
Normal file
29
vendor/sdl-3.2.10/src/filesystem/SDL_filesystem_c.h
vendored
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_filesystem_c_h_
|
||||
#define SDL_filesystem_c_h_
|
||||
|
||||
extern void SDL_InitFilesystem(void);
|
||||
extern void SDL_QuitFilesystem(void);
|
||||
|
||||
#endif
|
||||
|
||||
43
vendor/sdl-3.2.10/src/filesystem/SDL_sysfilesystem.h
vendored
Normal file
43
vendor/sdl-3.2.10/src/filesystem/SDL_sysfilesystem.h
vendored
Normal file
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#ifndef SDL_sysfilesystem_h_
|
||||
#define SDL_sysfilesystem_h_
|
||||
|
||||
// return a string that we can SDL_free(). It will be cached at the higher level.
|
||||
extern char *SDL_SYS_GetBasePath(void);
|
||||
extern char *SDL_SYS_GetPrefPath(const char *org, const char *app);
|
||||
extern char *SDL_SYS_GetUserFolder(SDL_Folder folder);
|
||||
extern char *SDL_SYS_GetCurrentDirectory(void);
|
||||
|
||||
extern bool SDL_SYS_EnumerateDirectory(const char *path, SDL_EnumerateDirectoryCallback cb, void *userdata);
|
||||
extern bool SDL_SYS_RemovePath(const char *path);
|
||||
extern bool SDL_SYS_RenamePath(const char *oldpath, const char *newpath);
|
||||
extern bool SDL_SYS_CopyFile(const char *oldpath, const char *newpath);
|
||||
extern bool SDL_SYS_CreateDirectory(const char *path);
|
||||
extern bool SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info);
|
||||
|
||||
typedef bool (*SDL_GlobEnumeratorFunc)(const char *path, SDL_EnumerateDirectoryCallback cb, void *cbuserdata, void *userdata);
|
||||
typedef bool (*SDL_GlobGetPathInfoFunc)(const char *path, SDL_PathInfo *info, void *userdata);
|
||||
extern char **SDL_InternalGlobDirectory(const char *path, const char *pattern, SDL_GlobFlags flags, int *count, SDL_GlobEnumeratorFunc enumerator, SDL_GlobGetPathInfoFunc getpathinfo, void *userdata);
|
||||
|
||||
#endif
|
||||
|
||||
62
vendor/sdl-3.2.10/src/filesystem/android/SDL_sysfilesystem.c
vendored
Normal file
62
vendor/sdl-3.2.10/src/filesystem/android/SDL_sysfilesystem.c
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_FILESYSTEM_ANDROID
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
// System dependent filesystem routines
|
||||
|
||||
#include "../SDL_sysfilesystem.h"
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
char *SDL_SYS_GetBasePath(void)
|
||||
{
|
||||
// The current working directory is / on Android
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
const char *path = SDL_GetAndroidInternalStoragePath();
|
||||
if (path) {
|
||||
size_t pathlen = SDL_strlen(path) + 2;
|
||||
char *fullpath = (char *)SDL_malloc(pathlen);
|
||||
if (!fullpath) {
|
||||
return NULL;
|
||||
}
|
||||
SDL_snprintf(fullpath, pathlen, "%s/", path);
|
||||
return fullpath;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetUserFolder(SDL_Folder folder)
|
||||
{
|
||||
/* TODO: see https://developer.android.com/reference/android/os/Environment#lfields
|
||||
and https://stackoverflow.com/questions/39332085/get-path-to-pictures-directory */
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif // SDL_FILESYSTEM_ANDROID
|
||||
240
vendor/sdl-3.2.10/src/filesystem/cocoa/SDL_sysfilesystem.m
vendored
Normal file
240
vendor/sdl-3.2.10/src/filesystem/cocoa/SDL_sysfilesystem.m
vendored
Normal file
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_FILESYSTEM_COCOA
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
// System dependent filesystem routines
|
||||
|
||||
#include "../SDL_sysfilesystem.h"
|
||||
|
||||
#include <Foundation/Foundation.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
char *SDL_SYS_GetBasePath(void)
|
||||
{
|
||||
@autoreleasepool {
|
||||
NSBundle *bundle = [NSBundle mainBundle];
|
||||
const char *baseType = [[[bundle infoDictionary] objectForKey:@"SDL_FILESYSTEM_BASE_DIR_TYPE"] UTF8String];
|
||||
const char *base = NULL;
|
||||
char *result = NULL;
|
||||
|
||||
if (baseType == NULL) {
|
||||
baseType = "resource";
|
||||
}
|
||||
if (SDL_strcasecmp(baseType, "bundle") == 0) {
|
||||
base = [[bundle bundlePath] fileSystemRepresentation];
|
||||
} else if (SDL_strcasecmp(baseType, "parent") == 0) {
|
||||
base = [[[bundle bundlePath] stringByDeletingLastPathComponent] fileSystemRepresentation];
|
||||
} else {
|
||||
// this returns the exedir for non-bundled and the resourceDir for bundled apps
|
||||
base = [[bundle resourcePath] fileSystemRepresentation];
|
||||
}
|
||||
|
||||
if (base) {
|
||||
const size_t len = SDL_strlen(base) + 2;
|
||||
result = (char *)SDL_malloc(len);
|
||||
if (result != NULL) {
|
||||
SDL_snprintf(result, len, "%s/", base);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
@autoreleasepool {
|
||||
char *result = NULL;
|
||||
NSArray *array;
|
||||
|
||||
if (!app) {
|
||||
SDL_InvalidParamError("app");
|
||||
return NULL;
|
||||
}
|
||||
if (!org) {
|
||||
org = "";
|
||||
}
|
||||
|
||||
#ifndef SDL_PLATFORM_TVOS
|
||||
array = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
|
||||
#else
|
||||
/* tvOS does not have persistent local storage!
|
||||
* The only place on-device where we can store data is
|
||||
* a cache directory that the OS can empty at any time.
|
||||
*
|
||||
* It's therefore very likely that save data will be erased
|
||||
* between sessions. If you want your app's save data to
|
||||
* actually stick around, you'll need to use iCloud storage.
|
||||
*/
|
||||
{
|
||||
static bool shown = false;
|
||||
if (!shown) {
|
||||
shown = true;
|
||||
SDL_LogCritical(SDL_LOG_CATEGORY_SYSTEM, "tvOS does not have persistent local storage! Use iCloud storage if you want your data to persist between sessions.");
|
||||
}
|
||||
}
|
||||
|
||||
array = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES);
|
||||
#endif // !SDL_PLATFORM_TVOS
|
||||
|
||||
if ([array count] > 0) { // we only want the first item in the list.
|
||||
NSString *str = [array objectAtIndex:0];
|
||||
const char *base = [str fileSystemRepresentation];
|
||||
if (base) {
|
||||
const size_t len = SDL_strlen(base) + SDL_strlen(org) + SDL_strlen(app) + 4;
|
||||
result = (char *)SDL_malloc(len);
|
||||
if (result != NULL) {
|
||||
char *ptr;
|
||||
if (*org) {
|
||||
SDL_snprintf(result, len, "%s/%s/%s/", base, org, app);
|
||||
} else {
|
||||
SDL_snprintf(result, len, "%s/%s/", base, app);
|
||||
}
|
||||
for (ptr = result + 1; *ptr; ptr++) {
|
||||
if (*ptr == '/') {
|
||||
*ptr = '\0';
|
||||
mkdir(result, 0700);
|
||||
*ptr = '/';
|
||||
}
|
||||
}
|
||||
mkdir(result, 0700);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetUserFolder(SDL_Folder folder)
|
||||
{
|
||||
@autoreleasepool {
|
||||
#ifdef SDL_PLATFORM_TVOS
|
||||
SDL_SetError("tvOS does not have persistent storage");
|
||||
return NULL;
|
||||
#else
|
||||
char *result = NULL;
|
||||
const char* base;
|
||||
NSArray *array;
|
||||
NSSearchPathDirectory dir;
|
||||
NSString *str;
|
||||
char *ptr;
|
||||
|
||||
switch (folder) {
|
||||
case SDL_FOLDER_HOME:
|
||||
base = SDL_getenv("HOME");
|
||||
|
||||
if (!base) {
|
||||
SDL_SetError("No $HOME environment variable available");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
goto append_slash;
|
||||
|
||||
case SDL_FOLDER_DESKTOP:
|
||||
dir = NSDesktopDirectory;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_DOCUMENTS:
|
||||
dir = NSDocumentDirectory;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_DOWNLOADS:
|
||||
dir = NSDownloadsDirectory;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_MUSIC:
|
||||
dir = NSMusicDirectory;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_PICTURES:
|
||||
dir = NSPicturesDirectory;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_PUBLICSHARE:
|
||||
dir = NSSharedPublicDirectory;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_SAVEDGAMES:
|
||||
SDL_SetError("Saved games folder not supported on Cocoa");
|
||||
return NULL;
|
||||
|
||||
case SDL_FOLDER_SCREENSHOTS:
|
||||
SDL_SetError("Screenshots folder not supported on Cocoa");
|
||||
return NULL;
|
||||
|
||||
case SDL_FOLDER_TEMPLATES:
|
||||
SDL_SetError("Templates folder not supported on Cocoa");
|
||||
return NULL;
|
||||
|
||||
case SDL_FOLDER_VIDEOS:
|
||||
dir = NSMoviesDirectory;
|
||||
break;
|
||||
|
||||
default:
|
||||
SDL_SetError("Invalid SDL_Folder: %d", (int) folder);
|
||||
return NULL;
|
||||
};
|
||||
|
||||
array = NSSearchPathForDirectoriesInDomains(dir, NSUserDomainMask, YES);
|
||||
|
||||
if ([array count] <= 0) {
|
||||
SDL_SetError("Directory not found");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
str = [array objectAtIndex:0];
|
||||
base = [str fileSystemRepresentation];
|
||||
if (!base) {
|
||||
SDL_SetError("Couldn't get folder path");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
append_slash:
|
||||
result = SDL_malloc(SDL_strlen(base) + 2);
|
||||
if (result == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (SDL_snprintf(result, SDL_strlen(base) + 2, "%s/", base) < 0) {
|
||||
SDL_SetError("Couldn't snprintf folder path for Cocoa: %s", base);
|
||||
SDL_free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (ptr = result + 1; *ptr; ptr++) {
|
||||
if (*ptr == '/') {
|
||||
*ptr = '\0';
|
||||
mkdir(result, 0700);
|
||||
*ptr = '/';
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
#endif // SDL_PLATFORM_TVOS
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SDL_FILESYSTEM_COCOA
|
||||
54
vendor/sdl-3.2.10/src/filesystem/dummy/SDL_sysfilesystem.c
vendored
Normal file
54
vendor/sdl-3.2.10/src/filesystem/dummy/SDL_sysfilesystem.c
vendored
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#if defined(SDL_FILESYSTEM_DUMMY) || defined(SDL_FILESYSTEM_DISABLED)
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
// System dependent filesystem routines
|
||||
|
||||
#include "../SDL_sysfilesystem.h"
|
||||
|
||||
char *SDL_SYS_GetBasePath(void)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetUserFolder(SDL_Folder folder)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetCurrentDirectory(void)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif // SDL_FILESYSTEM_DUMMY || SDL_FILESYSTEM_DISABLED
|
||||
62
vendor/sdl-3.2.10/src/filesystem/dummy/SDL_sysfsops.c
vendored
Normal file
62
vendor/sdl-3.2.10/src/filesystem/dummy/SDL_sysfsops.c
vendored
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#if defined(SDL_FSOPS_DUMMY)
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
// System dependent filesystem routines
|
||||
|
||||
#include "../SDL_sysfilesystem.h"
|
||||
|
||||
bool SDL_SYS_EnumerateDirectory(const char *path, SDL_EnumerateDirectoryCallback cb, void *userdata)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
bool SDL_SYS_RemovePath(const char *path)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
bool SDL_SYS_RenamePath(const char *oldpath, const char *newpath)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
bool SDL_SYS_CopyFile(const char *oldpath, const char *newpath)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
bool SDL_SYS_CreateDirectory(const char *path)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
bool SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info)
|
||||
{
|
||||
return SDL_Unsupported();
|
||||
}
|
||||
|
||||
#endif // SDL_FSOPS_DUMMY
|
||||
|
||||
116
vendor/sdl-3.2.10/src/filesystem/emscripten/SDL_sysfilesystem.c
vendored
Normal file
116
vendor/sdl-3.2.10/src/filesystem/emscripten/SDL_sysfilesystem.c
vendored
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_FILESYSTEM_EMSCRIPTEN
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
// System dependent filesystem routines
|
||||
|
||||
#include "../SDL_sysfilesystem.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <emscripten/emscripten.h>
|
||||
|
||||
char *SDL_SYS_GetBasePath(void)
|
||||
{
|
||||
return SDL_strdup("/");
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
const char *append = "/libsdl/";
|
||||
char *result;
|
||||
char *ptr = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
if (!app) {
|
||||
SDL_InvalidParamError("app");
|
||||
return NULL;
|
||||
}
|
||||
if (!org) {
|
||||
org = "";
|
||||
}
|
||||
|
||||
len = SDL_strlen(append) + SDL_strlen(org) + SDL_strlen(app) + 3;
|
||||
result = (char *)SDL_malloc(len);
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (*org) {
|
||||
SDL_snprintf(result, len, "%s%s/%s/", append, org, app);
|
||||
} else {
|
||||
SDL_snprintf(result, len, "%s%s/", append, app);
|
||||
}
|
||||
|
||||
for (ptr = result + 1; *ptr; ptr++) {
|
||||
if (*ptr == '/') {
|
||||
*ptr = '\0';
|
||||
if (mkdir(result, 0700) != 0 && errno != EEXIST) {
|
||||
goto error;
|
||||
}
|
||||
*ptr = '/';
|
||||
}
|
||||
}
|
||||
|
||||
if (mkdir(result, 0700) != 0 && errno != EEXIST) {
|
||||
error:
|
||||
SDL_SetError("Couldn't create directory '%s': '%s'", result, strerror(errno));
|
||||
SDL_free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetUserFolder(SDL_Folder folder)
|
||||
{
|
||||
const char *home = NULL;
|
||||
|
||||
if (folder != SDL_FOLDER_HOME) {
|
||||
SDL_SetError("Emscripten only supports the home folder");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
home = SDL_getenv("HOME");
|
||||
if (!home) {
|
||||
SDL_SetError("No $HOME environment variable available");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *result = SDL_malloc(SDL_strlen(home) + 2);
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (SDL_snprintf(result, SDL_strlen(home) + 2, "%s/", home) < 0) {
|
||||
SDL_SetError("Couldn't snprintf home path for Emscripten: %s", home);
|
||||
SDL_free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // SDL_FILESYSTEM_EMSCRIPTEN
|
||||
150
vendor/sdl-3.2.10/src/filesystem/gdk/SDL_sysfilesystem.cpp
vendored
Normal file
150
vendor/sdl-3.2.10/src/filesystem/gdk/SDL_sysfilesystem.cpp
vendored
Normal file
|
|
@ -0,0 +1,150 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
// System dependent filesystem routines
|
||||
|
||||
extern "C" {
|
||||
#include "../SDL_sysfilesystem.h"
|
||||
}
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
#include <SDL3/SDL_hints.h>
|
||||
#include <SDL3/SDL_system.h>
|
||||
#include <SDL3/SDL_filesystem.h>
|
||||
#include <XGameSaveFiles.h>
|
||||
|
||||
char *
|
||||
SDL_SYS_GetBasePath(void)
|
||||
{
|
||||
/* NOTE: This function is a UTF8 version of the Win32 SDL_GetBasePath()!
|
||||
* The GDK actually _recommends_ the 'A' functions over the 'W' functions :o
|
||||
*/
|
||||
DWORD buflen = 128;
|
||||
CHAR *path = NULL;
|
||||
DWORD len = 0;
|
||||
int i;
|
||||
|
||||
while (true) {
|
||||
void *ptr = SDL_realloc(path, buflen * sizeof(CHAR));
|
||||
if (!ptr) {
|
||||
SDL_free(path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path = (CHAR *)ptr;
|
||||
|
||||
len = GetModuleFileNameA(NULL, path, buflen);
|
||||
// if it truncated, then len >= buflen - 1
|
||||
// if there was enough room (or failure), len < buflen - 1
|
||||
if (len < buflen - 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
// buffer too small? Try again.
|
||||
buflen *= 2;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
SDL_free(path);
|
||||
WIN_SetError("Couldn't locate our .exe");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = len - 1; i > 0; i--) {
|
||||
if (path[i] == '\\') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(i > 0); // Should have been an absolute path.
|
||||
path[i + 1] = '\0'; // chop off filename.
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
XUserHandle user = NULL;
|
||||
XAsyncBlock block = { 0 };
|
||||
char *folderPath;
|
||||
HRESULT result;
|
||||
const char *csid = SDL_GetHint("SDL_GDK_SERVICE_CONFIGURATION_ID");
|
||||
|
||||
if (!app) {
|
||||
SDL_InvalidParamError("app");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// This should be set before calling SDL_GetPrefPath!
|
||||
if (!csid) {
|
||||
SDL_LogWarn(SDL_LOG_CATEGORY_SYSTEM, "Set SDL_GDK_SERVICE_CONFIGURATION_ID before calling SDL_GetPrefPath!");
|
||||
return SDL_strdup("T:\\");
|
||||
}
|
||||
|
||||
if (!SDL_GetGDKDefaultUser(&user)) {
|
||||
// Error already set, just return
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (FAILED(result = XGameSaveFilesGetFolderWithUiAsync(user, csid, &block))) {
|
||||
WIN_SetErrorFromHRESULT("XGameSaveFilesGetFolderWithUiAsync", result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
folderPath = (char*) SDL_malloc(MAX_PATH);
|
||||
do {
|
||||
result = XGameSaveFilesGetFolderWithUiResult(&block, MAX_PATH, folderPath);
|
||||
} while (result == E_PENDING);
|
||||
if (FAILED(result)) {
|
||||
WIN_SetErrorFromHRESULT("XGameSaveFilesGetFolderWithUiResult", result);
|
||||
SDL_free(folderPath);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* We aren't using 'app' here because the container rules are a lot more
|
||||
* strict than the NTFS rules, so it will most likely be invalid :(
|
||||
*/
|
||||
SDL_strlcat(folderPath, "\\SDLPrefPath\\", MAX_PATH);
|
||||
if (CreateDirectoryA(folderPath, NULL) == FALSE) {
|
||||
if (GetLastError() != ERROR_ALREADY_EXISTS) {
|
||||
WIN_SetError("CreateDirectoryA");
|
||||
SDL_free(folderPath);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
return folderPath;
|
||||
}
|
||||
|
||||
// TODO
|
||||
char *SDL_SYS_GetUserFolder(SDL_Folder folder)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// TODO
|
||||
char *SDL_SYS_GetCurrentDirectory(void)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
156
vendor/sdl-3.2.10/src/filesystem/haiku/SDL_sysfilesystem.cc
vendored
Normal file
156
vendor/sdl-3.2.10/src/filesystem/haiku/SDL_sysfilesystem.cc
vendored
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_FILESYSTEM_HAIKU
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
// System dependent filesystem routines
|
||||
|
||||
extern "C" {
|
||||
#include "../SDL_sysfilesystem.h"
|
||||
}
|
||||
|
||||
#include <kernel/image.h>
|
||||
#include <storage/Directory.h>
|
||||
#include <storage/Entry.h>
|
||||
#include <storage/FindDirectory.h>
|
||||
#include <storage/Path.h>
|
||||
|
||||
|
||||
char *SDL_SYS_GetBasePath(void)
|
||||
{
|
||||
char name[MAXPATHLEN];
|
||||
|
||||
if (find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH, NULL, name, sizeof(name)) != B_OK) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
BEntry entry(name, true);
|
||||
BPath path;
|
||||
status_t rc = entry.GetPath(&path); // (path) now has binary's path.
|
||||
SDL_assert(rc == B_OK);
|
||||
rc = path.GetParent(&path); // chop filename, keep directory.
|
||||
SDL_assert(rc == B_OK);
|
||||
const char *str = path.Path();
|
||||
SDL_assert(str != NULL);
|
||||
|
||||
const size_t len = SDL_strlen(str);
|
||||
char *result = (char *) SDL_malloc(len + 2);
|
||||
if (result) {
|
||||
SDL_memcpy(result, str, len);
|
||||
result[len] = '/';
|
||||
result[len+1] = '\0';
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
// !!! FIXME: is there a better way to do this?
|
||||
const char *home = SDL_getenv("HOME");
|
||||
const char *append = "/config/settings/";
|
||||
size_t len = SDL_strlen(home);
|
||||
|
||||
if (!app) {
|
||||
SDL_InvalidParamError("app");
|
||||
return NULL;
|
||||
}
|
||||
if (!org) {
|
||||
org = "";
|
||||
}
|
||||
|
||||
if (!len || (home[len - 1] == '/')) {
|
||||
++append; // home empty or ends with separator, skip the one from append
|
||||
}
|
||||
len += SDL_strlen(append) + SDL_strlen(org) + SDL_strlen(app) + 3;
|
||||
char *result = (char *) SDL_malloc(len);
|
||||
if (result) {
|
||||
if (*org) {
|
||||
SDL_snprintf(result, len, "%s%s%s/%s/", home, append, org, app);
|
||||
} else {
|
||||
SDL_snprintf(result, len, "%s%s%s/", home, append, app);
|
||||
}
|
||||
create_directory(result, 0700); // Haiku api: creates missing dirs
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetUserFolder(SDL_Folder folder)
|
||||
{
|
||||
const char *home = NULL;
|
||||
char *result;
|
||||
|
||||
home = SDL_getenv("HOME");
|
||||
if (!home) {
|
||||
SDL_SetError("No $HOME environment variable available");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
switch (folder) {
|
||||
case SDL_FOLDER_HOME:
|
||||
result = (char *) SDL_malloc(SDL_strlen(home) + 2);
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (SDL_snprintf(result, SDL_strlen(home) + 2, "%s/", home) < 0) {
|
||||
SDL_SetError("Couldn't snprintf home path for Haiku: %s", home);
|
||||
SDL_free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
// TODO: Is Haiku's desktop folder always ~/Desktop/ ?
|
||||
case SDL_FOLDER_DESKTOP:
|
||||
result = (char *) SDL_malloc(SDL_strlen(home) + 10);
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (SDL_snprintf(result, SDL_strlen(home) + 10, "%s/Desktop/", home) < 0) {
|
||||
SDL_SetError("Couldn't snprintf desktop path for Haiku: %s/Desktop/", home);
|
||||
SDL_free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
|
||||
case SDL_FOLDER_DOCUMENTS:
|
||||
case SDL_FOLDER_DOWNLOADS:
|
||||
case SDL_FOLDER_MUSIC:
|
||||
case SDL_FOLDER_PICTURES:
|
||||
case SDL_FOLDER_PUBLICSHARE:
|
||||
case SDL_FOLDER_SAVEDGAMES:
|
||||
case SDL_FOLDER_SCREENSHOTS:
|
||||
case SDL_FOLDER_TEMPLATES:
|
||||
case SDL_FOLDER_VIDEOS:
|
||||
default:
|
||||
SDL_SetError("Only HOME and DESKTOP available on Haiku");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // SDL_FILESYSTEM_HAIKU
|
||||
90
vendor/sdl-3.2.10/src/filesystem/n3ds/SDL_sysfilesystem.c
vendored
Normal file
90
vendor/sdl-3.2.10/src/filesystem/n3ds/SDL_sysfilesystem.c
vendored
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_FILESYSTEM_N3DS
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
// System dependent filesystem routines
|
||||
|
||||
#include "../SDL_sysfilesystem.h"
|
||||
|
||||
#include <3ds.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
|
||||
static char *MakePrefPath(const char *app);
|
||||
static bool CreatePrefPathDir(const char *pref);
|
||||
|
||||
char *SDL_SYS_GetBasePath(void)
|
||||
{
|
||||
char *base_path = SDL_strdup("romfs:/");
|
||||
return base_path;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
char *pref_path = NULL;
|
||||
if (!app) {
|
||||
SDL_InvalidParamError("app");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
pref_path = MakePrefPath(app);
|
||||
if (!pref_path) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!CreatePrefPathDir(pref_path)) {
|
||||
SDL_free(pref_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return pref_path;
|
||||
}
|
||||
|
||||
// TODO
|
||||
char *SDL_SYS_GetUserFolder(SDL_Folder folder)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *MakePrefPath(const char *app)
|
||||
{
|
||||
char *pref_path;
|
||||
if (SDL_asprintf(&pref_path, "sdmc:/3ds/%s/", app) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
return pref_path;
|
||||
}
|
||||
|
||||
static bool CreatePrefPathDir(const char *pref)
|
||||
{
|
||||
int result = mkdir(pref, 0666);
|
||||
|
||||
if (result == -1 && errno != EEXIST) {
|
||||
return SDL_SetError("Failed to create '%s' (%s)", pref, strerror(errno));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // SDL_FILESYSTEM_N3DS
|
||||
246
vendor/sdl-3.2.10/src/filesystem/posix/SDL_sysfsops.c
vendored
Normal file
246
vendor/sdl-3.2.10/src/filesystem/posix/SDL_sysfsops.c
vendored
Normal file
|
|
@ -0,0 +1,246 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#if defined(SDL_FSOPS_POSIX)
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
// System dependent filesystem routines
|
||||
|
||||
#include "../SDL_sysfilesystem.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
bool SDL_SYS_EnumerateDirectory(const char *path, SDL_EnumerateDirectoryCallback cb, void *userdata)
|
||||
{
|
||||
char *pathwithsep = NULL;
|
||||
int pathwithseplen = SDL_asprintf(&pathwithsep, "%s/", path);
|
||||
if ((pathwithseplen == -1) || (!pathwithsep)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// trim down to a single path separator at the end, in case the caller added one or more.
|
||||
pathwithseplen--;
|
||||
while ((pathwithseplen >= 0) && (pathwithsep[pathwithseplen] == '/')) {
|
||||
pathwithsep[pathwithseplen--] = '\0';
|
||||
}
|
||||
|
||||
DIR *dir = opendir(pathwithsep);
|
||||
if (!dir) {
|
||||
SDL_free(pathwithsep);
|
||||
return SDL_SetError("Can't open directory: %s", strerror(errno));
|
||||
}
|
||||
|
||||
// make sure there's a path separator at the end now for the actual callback.
|
||||
pathwithsep[++pathwithseplen] = '/';
|
||||
pathwithsep[++pathwithseplen] = '\0';
|
||||
|
||||
SDL_EnumerationResult result = SDL_ENUM_CONTINUE;
|
||||
struct dirent *ent;
|
||||
while ((result == SDL_ENUM_CONTINUE) && ((ent = readdir(dir)) != NULL)) {
|
||||
const char *name = ent->d_name;
|
||||
if ((SDL_strcmp(name, ".") == 0) || (SDL_strcmp(name, "..") == 0)) {
|
||||
continue;
|
||||
}
|
||||
result = cb(userdata, pathwithsep, name);
|
||||
}
|
||||
|
||||
closedir(dir);
|
||||
|
||||
SDL_free(pathwithsep);
|
||||
|
||||
return (result != SDL_ENUM_FAILURE);
|
||||
}
|
||||
|
||||
bool SDL_SYS_RemovePath(const char *path)
|
||||
{
|
||||
int rc = remove(path);
|
||||
if (rc < 0) {
|
||||
if (errno == ENOENT) {
|
||||
// It's already gone, this is a success
|
||||
return true;
|
||||
}
|
||||
return SDL_SetError("Can't remove path: %s", strerror(errno));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDL_SYS_RenamePath(const char *oldpath, const char *newpath)
|
||||
{
|
||||
if (rename(oldpath, newpath) < 0) {
|
||||
return SDL_SetError("Can't rename path: %s", strerror(errno));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDL_SYS_CopyFile(const char *oldpath, const char *newpath)
|
||||
{
|
||||
char *buffer = NULL;
|
||||
SDL_IOStream *input = NULL;
|
||||
SDL_IOStream *output = NULL;
|
||||
const size_t maxlen = 4096;
|
||||
size_t len;
|
||||
bool result = false;
|
||||
|
||||
input = SDL_IOFromFile(oldpath, "rb");
|
||||
if (!input) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
output = SDL_IOFromFile(newpath, "wb");
|
||||
if (!output) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
buffer = (char *)SDL_malloc(maxlen);
|
||||
if (!buffer) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
while ((len = SDL_ReadIO(input, buffer, maxlen)) > 0) {
|
||||
if (SDL_WriteIO(output, buffer, len) < len) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
if (SDL_GetIOStatus(input) != SDL_IO_STATUS_EOF) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
SDL_CloseIO(input);
|
||||
input = NULL;
|
||||
|
||||
if (!SDL_FlushIO(output)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
result = SDL_CloseIO(output);
|
||||
output = NULL; // it's gone, even if it failed.
|
||||
|
||||
done:
|
||||
if (output) {
|
||||
SDL_CloseIO(output);
|
||||
}
|
||||
if (input) {
|
||||
SDL_CloseIO(input);
|
||||
}
|
||||
SDL_free(buffer);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SDL_SYS_CreateDirectory(const char *path)
|
||||
{
|
||||
const int rc = mkdir(path, 0770);
|
||||
if (rc < 0) {
|
||||
const int origerrno = errno;
|
||||
if (origerrno == EEXIST) {
|
||||
struct stat statbuf;
|
||||
if ((stat(path, &statbuf) == 0) && (S_ISDIR(statbuf.st_mode))) {
|
||||
return true; // it already exists and it's a directory, consider it success.
|
||||
}
|
||||
}
|
||||
return SDL_SetError("Can't create directory: %s", strerror(origerrno));
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info)
|
||||
{
|
||||
struct stat statbuf;
|
||||
const int rc = stat(path, &statbuf);
|
||||
if (rc < 0) {
|
||||
return SDL_SetError("Can't stat: %s", strerror(errno));
|
||||
} else if (S_ISREG(statbuf.st_mode)) {
|
||||
info->type = SDL_PATHTYPE_FILE;
|
||||
info->size = (Uint64) statbuf.st_size;
|
||||
} else if (S_ISDIR(statbuf.st_mode)) {
|
||||
info->type = SDL_PATHTYPE_DIRECTORY;
|
||||
info->size = 0;
|
||||
} else {
|
||||
info->type = SDL_PATHTYPE_OTHER;
|
||||
info->size = (Uint64) statbuf.st_size;
|
||||
}
|
||||
|
||||
#if defined(HAVE_ST_MTIM)
|
||||
// POSIX.1-2008 standard
|
||||
info->create_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_ctim.tv_sec) + statbuf.st_ctim.tv_nsec;
|
||||
info->modify_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_mtim.tv_sec) + statbuf.st_mtim.tv_nsec;
|
||||
info->access_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_atim.tv_sec) + statbuf.st_atim.tv_nsec;
|
||||
#elif defined(SDL_PLATFORM_APPLE)
|
||||
/* Apple platform stat structs use 'st_*timespec' naming. */
|
||||
info->create_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_ctimespec.tv_sec) + statbuf.st_ctimespec.tv_nsec;
|
||||
info->modify_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_mtimespec.tv_sec) + statbuf.st_mtimespec.tv_nsec;
|
||||
info->access_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_atimespec.tv_sec) + statbuf.st_atimespec.tv_nsec;
|
||||
#else
|
||||
info->create_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_ctime);
|
||||
info->modify_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_mtime);
|
||||
info->access_time = (SDL_Time)SDL_SECONDS_TO_NS(statbuf.st_atime);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
// Note that this isn't actually part of filesystem, not fsops, but everything that uses posix fsops uses this implementation, even with separate filesystem code.
|
||||
char *SDL_SYS_GetCurrentDirectory(void)
|
||||
{
|
||||
size_t buflen = 64;
|
||||
char *buf = NULL;
|
||||
|
||||
while (true) {
|
||||
void *ptr = SDL_realloc(buf, buflen);
|
||||
if (!ptr) {
|
||||
SDL_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
buf = (char *) ptr;
|
||||
|
||||
if (getcwd(buf, buflen-1) != NULL) {
|
||||
break; // we got it!
|
||||
}
|
||||
|
||||
if (errno == ERANGE) {
|
||||
buflen *= 2; // try again with a bigger buffer.
|
||||
continue;
|
||||
}
|
||||
|
||||
SDL_free(buf);
|
||||
SDL_SetError("getcwd failed: %s", strerror(errno));
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// make sure there's a path separator at the end.
|
||||
SDL_assert(SDL_strlen(buf) < (buflen + 2));
|
||||
buflen = SDL_strlen(buf);
|
||||
if ((buflen == 0) || (buf[buflen-1] != '/')) {
|
||||
buf[buflen] = '/';
|
||||
buf[buflen + 1] = '\0';
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
#endif // SDL_FSOPS_POSIX
|
||||
|
||||
119
vendor/sdl-3.2.10/src/filesystem/ps2/SDL_sysfilesystem.c
vendored
Normal file
119
vendor/sdl-3.2.10/src/filesystem/ps2/SDL_sysfilesystem.c
vendored
Normal file
|
|
@ -0,0 +1,119 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_FILESYSTEM_PS2
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
// System dependent filesystem routines
|
||||
|
||||
#include "../SDL_sysfilesystem.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
char *SDL_SYS_GetBasePath(void)
|
||||
{
|
||||
char *result = NULL;
|
||||
size_t len;
|
||||
char cwd[FILENAME_MAX];
|
||||
|
||||
getcwd(cwd, sizeof(cwd));
|
||||
len = SDL_strlen(cwd) + 2;
|
||||
result = (char *)SDL_malloc(len);
|
||||
if (result) {
|
||||
SDL_snprintf(result, len, "%s/", cwd);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// Do a recursive mkdir of parents folders
|
||||
static void recursive_mkdir(const char *dir)
|
||||
{
|
||||
char tmp[FILENAME_MAX];
|
||||
const char *base = SDL_GetBasePath();
|
||||
char *p = NULL;
|
||||
size_t len;
|
||||
|
||||
SDL_snprintf(tmp, sizeof(tmp), "%s", dir);
|
||||
len = SDL_strlen(tmp);
|
||||
if (tmp[len - 1] == '/') {
|
||||
tmp[len - 1] = 0;
|
||||
}
|
||||
|
||||
for (p = tmp + 1; *p; p++) {
|
||||
if (*p == '/') {
|
||||
*p = 0;
|
||||
// Just creating subfolders from current path
|
||||
if (base && SDL_strstr(tmp, base) != NULL) {
|
||||
mkdir(tmp, S_IRWXU);
|
||||
}
|
||||
|
||||
*p = '/';
|
||||
}
|
||||
}
|
||||
|
||||
mkdir(tmp, S_IRWXU);
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
char *result = NULL;
|
||||
size_t len;
|
||||
|
||||
if (!app) {
|
||||
SDL_InvalidParamError("app");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!org) {
|
||||
org = "";
|
||||
}
|
||||
|
||||
const char *base = SDL_GetBasePath();
|
||||
if (!base) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = SDL_strlen(base) + SDL_strlen(org) + SDL_strlen(app) + 4;
|
||||
result = (char *)SDL_malloc(len);
|
||||
if (result) {
|
||||
if (*org) {
|
||||
SDL_snprintf(result, len, "%s%s/%s/", base, org, app);
|
||||
} else {
|
||||
SDL_snprintf(result, len, "%s%s/", base, app);
|
||||
}
|
||||
|
||||
recursive_mkdir(result);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO
|
||||
char *SDL_SYS_GetUserFolder(SDL_Folder folder)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif // SDL_FILESYSTEM_PS2
|
||||
89
vendor/sdl-3.2.10/src/filesystem/psp/SDL_sysfilesystem.c
vendored
Normal file
89
vendor/sdl-3.2.10/src/filesystem/psp/SDL_sysfilesystem.c
vendored
Normal file
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_FILESYSTEM_PSP
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
// System dependent filesystem routines
|
||||
|
||||
#include "../SDL_sysfilesystem.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
|
||||
char *SDL_SYS_GetBasePath(void)
|
||||
{
|
||||
char *result = NULL;
|
||||
size_t len;
|
||||
char cwd[FILENAME_MAX];
|
||||
|
||||
getcwd(cwd, sizeof(cwd));
|
||||
len = SDL_strlen(cwd) + 2;
|
||||
result = (char *)SDL_malloc(len);
|
||||
if (result) {
|
||||
SDL_snprintf(result, len, "%s/", cwd);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
char *result = NULL;
|
||||
size_t len;
|
||||
if (!app) {
|
||||
SDL_InvalidParamError("app");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const char *base = SDL_GetBasePath();
|
||||
if (!base) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (!org) {
|
||||
org = "";
|
||||
}
|
||||
|
||||
len = SDL_strlen(base) + SDL_strlen(org) + SDL_strlen(app) + 4;
|
||||
result = (char *)SDL_malloc(len);
|
||||
if (result) {
|
||||
if (*org) {
|
||||
SDL_snprintf(result, len, "%s%s/%s/", base, org, app);
|
||||
} else {
|
||||
SDL_snprintf(result, len, "%s%s/", base, app);
|
||||
}
|
||||
|
||||
mkdir(result, 0755);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO
|
||||
char *SDL_SYS_GetUserFolder(SDL_Folder folder)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif // SDL_FILESYSTEM_PSP
|
||||
208
vendor/sdl-3.2.10/src/filesystem/riscos/SDL_sysfilesystem.c
vendored
Normal file
208
vendor/sdl-3.2.10/src/filesystem/riscos/SDL_sysfilesystem.c
vendored
Normal file
|
|
@ -0,0 +1,208 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_FILESYSTEM_RISCOS
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
// System dependent filesystem routines
|
||||
|
||||
#include "../SDL_sysfilesystem.h"
|
||||
|
||||
#include <kernel.h>
|
||||
#include <swis.h>
|
||||
#include <unixlib/local.h>
|
||||
|
||||
// Wrapper around __unixify_std that uses SDL's memory allocators
|
||||
static char *SDL_unixify_std(const char *ro_path, char *buffer, size_t buf_len, int filetype)
|
||||
{
|
||||
const char *const in_buf = buffer; // = NULL if we allocate the buffer.
|
||||
|
||||
if (!buffer) {
|
||||
/* This matches the logic in __unixify, with an additional byte for the
|
||||
* extra path separator.
|
||||
*/
|
||||
buf_len = SDL_strlen(ro_path) + 14 + 1;
|
||||
buffer = SDL_malloc(buf_len);
|
||||
|
||||
if (!buffer) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (!__unixify_std(ro_path, buffer, buf_len, filetype)) {
|
||||
if (!in_buf) {
|
||||
SDL_free(buffer);
|
||||
}
|
||||
|
||||
SDL_SetError("Could not convert '%s' to a Unix-style path", ro_path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* HACK: It's necessary to add an extra path separator here since SDL's API
|
||||
* requires it, however paths with trailing separators aren't normally valid
|
||||
* on RISC OS.
|
||||
*/
|
||||
if (__get_riscosify_control() & __RISCOSIFY_NO_PROCESS)
|
||||
SDL_strlcat(buffer, ".", buf_len);
|
||||
else
|
||||
SDL_strlcat(buffer, "/", buf_len);
|
||||
|
||||
return buffer;
|
||||
}
|
||||
|
||||
static char *canonicalisePath(const char *path, const char *pathVar)
|
||||
{
|
||||
_kernel_oserror *error;
|
||||
_kernel_swi_regs regs;
|
||||
char *buf;
|
||||
|
||||
regs.r[0] = 37;
|
||||
regs.r[1] = (int)path;
|
||||
regs.r[2] = 0;
|
||||
regs.r[3] = (int)pathVar;
|
||||
regs.r[4] = 0;
|
||||
regs.r[5] = 0;
|
||||
error = _kernel_swi(OS_FSControl, ®s, ®s);
|
||||
if (error) {
|
||||
SDL_SetError("Couldn't canonicalise path: %s", error->errmess);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
regs.r[5] = 1 - regs.r[5];
|
||||
buf = SDL_malloc(regs.r[5]);
|
||||
if (!buf) {
|
||||
return NULL;
|
||||
}
|
||||
regs.r[2] = (int)buf;
|
||||
error = _kernel_swi(OS_FSControl, ®s, ®s);
|
||||
if (error) {
|
||||
SDL_SetError("Couldn't canonicalise path: %s", error->errmess);
|
||||
SDL_free(buf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
static _kernel_oserror *createDirectoryRecursive(char *path)
|
||||
{
|
||||
char *ptr = NULL;
|
||||
_kernel_oserror *error;
|
||||
_kernel_swi_regs regs;
|
||||
regs.r[0] = 8;
|
||||
regs.r[1] = (int)path;
|
||||
regs.r[2] = 0;
|
||||
|
||||
for (ptr = path + 1; *ptr; ptr++) {
|
||||
if (*ptr == '.') {
|
||||
*ptr = '\0';
|
||||
error = _kernel_swi(OS_File, ®s, ®s);
|
||||
*ptr = '.';
|
||||
if (error) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
}
|
||||
return _kernel_swi(OS_File, ®s, ®s);
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetBasePath(void)
|
||||
{
|
||||
_kernel_swi_regs regs;
|
||||
_kernel_oserror *error;
|
||||
char *canon, *ptr, *result;
|
||||
|
||||
error = _kernel_swi(OS_GetEnv, ®s, ®s);
|
||||
if (error) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
canon = canonicalisePath((const char *)regs.r[0], "Run$Path");
|
||||
if (!canon) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
// chop off filename.
|
||||
ptr = SDL_strrchr(canon, '.');
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
}
|
||||
|
||||
result = SDL_unixify_std(canon, NULL, 0, __RISCOSIFY_FILETYPE_NOTSPECIFIED);
|
||||
SDL_free(canon);
|
||||
return result;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
char *canon, *dir, *result;
|
||||
size_t len;
|
||||
_kernel_oserror *error;
|
||||
|
||||
if (!app) {
|
||||
SDL_InvalidParamError("app");
|
||||
return NULL;
|
||||
}
|
||||
if (!org) {
|
||||
org = "";
|
||||
}
|
||||
|
||||
canon = canonicalisePath("<Choices$Write>", "Run$Path");
|
||||
if (!canon) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
len = SDL_strlen(canon) + SDL_strlen(org) + SDL_strlen(app) + 4;
|
||||
dir = (char *)SDL_malloc(len);
|
||||
if (!dir) {
|
||||
SDL_free(canon);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (*org) {
|
||||
SDL_snprintf(dir, len, "%s.%s.%s", canon, org, app);
|
||||
} else {
|
||||
SDL_snprintf(dir, len, "%s.%s", canon, app);
|
||||
}
|
||||
|
||||
SDL_free(canon);
|
||||
|
||||
error = createDirectoryRecursive(dir);
|
||||
if (error) {
|
||||
SDL_SetError("Couldn't create directory: %s", error->errmess);
|
||||
SDL_free(dir);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = SDL_unixify_std(dir, NULL, 0, __RISCOSIFY_FILETYPE_NOTSPECIFIED);
|
||||
SDL_free(dir);
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO
|
||||
char *SDL_SYS_GetUserFolder(SDL_Folder folder)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif // SDL_FILESYSTEM_RISCOS
|
||||
618
vendor/sdl-3.2.10/src/filesystem/unix/SDL_sysfilesystem.c
vendored
Normal file
618
vendor/sdl-3.2.10/src/filesystem/unix/SDL_sysfilesystem.c
vendored
Normal file
|
|
@ -0,0 +1,618 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_FILESYSTEM_UNIX
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
// System dependent filesystem routines
|
||||
|
||||
#include "../SDL_sysfilesystem.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#if defined(SDL_PLATFORM_FREEBSD) || defined(SDL_PLATFORM_OPENBSD)
|
||||
#include <sys/sysctl.h>
|
||||
#endif
|
||||
|
||||
static char *readSymLink(const char *path)
|
||||
{
|
||||
char *result = NULL;
|
||||
ssize_t len = 64;
|
||||
ssize_t rc = -1;
|
||||
|
||||
while (1) {
|
||||
char *ptr = (char *)SDL_realloc(result, (size_t)len);
|
||||
if (!ptr) {
|
||||
break;
|
||||
}
|
||||
|
||||
result = ptr;
|
||||
|
||||
rc = readlink(path, result, len);
|
||||
if (rc == -1) {
|
||||
break; // not a symlink, i/o error, etc.
|
||||
} else if (rc < len) {
|
||||
result[rc] = '\0'; // readlink doesn't null-terminate.
|
||||
return result; // we're good to go.
|
||||
}
|
||||
|
||||
len *= 2; // grow buffer, try again.
|
||||
}
|
||||
|
||||
SDL_free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef SDL_PLATFORM_OPENBSD
|
||||
static char *search_path_for_binary(const char *bin)
|
||||
{
|
||||
const char *envr_real = SDL_getenv("PATH");
|
||||
char *envr;
|
||||
size_t alloc_size;
|
||||
char *exe = NULL;
|
||||
char *start = envr;
|
||||
char *ptr;
|
||||
|
||||
if (!envr_real) {
|
||||
SDL_SetError("No $PATH set");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
envr = SDL_strdup(envr_real);
|
||||
if (!envr) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SDL_assert(bin != NULL);
|
||||
|
||||
alloc_size = SDL_strlen(bin) + SDL_strlen(envr) + 2;
|
||||
exe = (char *)SDL_malloc(alloc_size);
|
||||
|
||||
do {
|
||||
ptr = SDL_strchr(start, ':'); // find next $PATH separator.
|
||||
if (ptr != start) {
|
||||
if (ptr) {
|
||||
*ptr = '\0';
|
||||
}
|
||||
|
||||
// build full binary path...
|
||||
SDL_snprintf(exe, alloc_size, "%s%s%s", start, (ptr && (ptr[-1] == '/')) ? "" : "/", bin);
|
||||
|
||||
if (access(exe, X_OK) == 0) { // Exists as executable? We're done.
|
||||
SDL_free(envr);
|
||||
return exe;
|
||||
}
|
||||
}
|
||||
start = ptr + 1; // start points to beginning of next element.
|
||||
} while (ptr);
|
||||
|
||||
SDL_free(envr);
|
||||
SDL_free(exe);
|
||||
|
||||
SDL_SetError("Process not found in $PATH");
|
||||
return NULL; // doesn't exist in path.
|
||||
}
|
||||
#endif
|
||||
|
||||
char *SDL_SYS_GetBasePath(void)
|
||||
{
|
||||
char *result = NULL;
|
||||
|
||||
#ifdef SDL_PLATFORM_FREEBSD
|
||||
char fullpath[PATH_MAX];
|
||||
size_t buflen = sizeof(fullpath);
|
||||
const int mib[] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 };
|
||||
if (sysctl(mib, SDL_arraysize(mib), fullpath, &buflen, NULL, 0) != -1) {
|
||||
result = SDL_strdup(fullpath);
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#ifdef SDL_PLATFORM_OPENBSD
|
||||
// Please note that this will fail if the process was launched with a relative path and $PWD + the cwd have changed, or argv is altered. So don't do that. Or add a new sysctl to OpenBSD.
|
||||
char **cmdline;
|
||||
size_t len;
|
||||
const int mib[] = { CTL_KERN, KERN_PROC_ARGS, getpid(), KERN_PROC_ARGV };
|
||||
if (sysctl(mib, 4, NULL, &len, NULL, 0) != -1) {
|
||||
char *exe, *pwddst;
|
||||
char *realpathbuf = (char *)SDL_malloc(PATH_MAX + 1);
|
||||
if (!realpathbuf) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
cmdline = SDL_malloc(len);
|
||||
if (!cmdline) {
|
||||
SDL_free(realpathbuf);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
sysctl(mib, 4, cmdline, &len, NULL, 0);
|
||||
|
||||
exe = cmdline[0];
|
||||
pwddst = NULL;
|
||||
if (SDL_strchr(exe, '/') == NULL) { // not a relative or absolute path, check $PATH for it
|
||||
exe = search_path_for_binary(cmdline[0]);
|
||||
} else {
|
||||
if (exe && *exe == '.') {
|
||||
const char *pwd = SDL_getenv("PWD");
|
||||
if (pwd && *pwd) {
|
||||
SDL_asprintf(&pwddst, "%s/%s", pwd, exe);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (exe) {
|
||||
if (!pwddst) {
|
||||
if (realpath(exe, realpathbuf) != NULL) {
|
||||
result = realpathbuf;
|
||||
}
|
||||
} else {
|
||||
if (realpath(pwddst, realpathbuf) != NULL) {
|
||||
result = realpathbuf;
|
||||
}
|
||||
SDL_free(pwddst);
|
||||
}
|
||||
|
||||
if (exe != cmdline[0]) {
|
||||
SDL_free(exe);
|
||||
}
|
||||
}
|
||||
|
||||
if (!result) {
|
||||
SDL_free(realpathbuf);
|
||||
}
|
||||
|
||||
SDL_free(cmdline);
|
||||
}
|
||||
#endif
|
||||
|
||||
// is a Linux-style /proc filesystem available?
|
||||
if (!result && (access("/proc", F_OK) == 0)) {
|
||||
/* !!! FIXME: after 2.0.6 ships, let's delete this code and just
|
||||
use the /proc/%llu version. There's no reason to have
|
||||
two copies of this plus all the #ifdefs. --ryan. */
|
||||
#ifdef SDL_PLATFORM_FREEBSD
|
||||
result = readSymLink("/proc/curproc/file");
|
||||
#elif defined(SDL_PLATFORM_NETBSD)
|
||||
result = readSymLink("/proc/curproc/exe");
|
||||
#elif defined(SDL_PLATFORM_SOLARIS)
|
||||
result = readSymLink("/proc/self/path/a.out");
|
||||
#else
|
||||
result = readSymLink("/proc/self/exe"); // linux.
|
||||
if (!result) {
|
||||
// older kernels don't have /proc/self ... try PID version...
|
||||
char path[64];
|
||||
const int rc = SDL_snprintf(path, sizeof(path),
|
||||
"/proc/%llu/exe",
|
||||
(unsigned long long)getpid());
|
||||
if ((rc > 0) && (rc < sizeof(path))) {
|
||||
result = readSymLink(path);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifdef SDL_PLATFORM_SOLARIS // try this as a fallback if /proc didn't pan out
|
||||
if (!result) {
|
||||
const char *path = getexecname();
|
||||
if ((path) && (path[0] == '/')) { // must be absolute path...
|
||||
result = SDL_strdup(path);
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
/* If we had access to argv[0] here, we could check it for a path,
|
||||
or troll through $PATH looking for it, too. */
|
||||
|
||||
if (result) { // chop off filename.
|
||||
char *ptr = SDL_strrchr(result, '/');
|
||||
if (ptr) {
|
||||
*(ptr + 1) = '\0';
|
||||
} else { // shouldn't happen, but just in case...
|
||||
SDL_free(result);
|
||||
result = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
if (result) {
|
||||
// try to shrink buffer...
|
||||
char *ptr = (char *)SDL_realloc(result, SDL_strlen(result) + 1);
|
||||
if (ptr) {
|
||||
result = ptr; // oh well if it failed.
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
/*
|
||||
* We use XDG's base directory spec, even if you're not on Linux.
|
||||
* This isn't strictly correct, but the results are relatively sane
|
||||
* in any case.
|
||||
*
|
||||
* http://standards.freedesktop.org/basedir-spec/basedir-spec-latest.html
|
||||
*/
|
||||
const char *envr = SDL_getenv("XDG_DATA_HOME");
|
||||
const char *append;
|
||||
char *result = NULL;
|
||||
char *ptr = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
if (!app) {
|
||||
SDL_InvalidParamError("app");
|
||||
return NULL;
|
||||
}
|
||||
if (!org) {
|
||||
org = "";
|
||||
}
|
||||
|
||||
if (!envr) {
|
||||
// You end up with "$HOME/.local/share/Game Name 2"
|
||||
envr = SDL_getenv("HOME");
|
||||
if (!envr) {
|
||||
// we could take heroic measures with /etc/passwd, but oh well.
|
||||
SDL_SetError("neither XDG_DATA_HOME nor HOME environment is set");
|
||||
return NULL;
|
||||
}
|
||||
append = "/.local/share/";
|
||||
} else {
|
||||
append = "/";
|
||||
}
|
||||
|
||||
len = SDL_strlen(envr);
|
||||
if (envr[len - 1] == '/') {
|
||||
append += 1;
|
||||
}
|
||||
|
||||
len += SDL_strlen(append) + SDL_strlen(org) + SDL_strlen(app) + 3;
|
||||
result = (char *)SDL_malloc(len);
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (*org) {
|
||||
(void)SDL_snprintf(result, len, "%s%s%s/%s/", envr, append, org, app);
|
||||
} else {
|
||||
(void)SDL_snprintf(result, len, "%s%s%s/", envr, append, app);
|
||||
}
|
||||
|
||||
for (ptr = result + 1; *ptr; ptr++) {
|
||||
if (*ptr == '/') {
|
||||
*ptr = '\0';
|
||||
if (mkdir(result, 0700) != 0 && errno != EEXIST) {
|
||||
goto error;
|
||||
}
|
||||
*ptr = '/';
|
||||
}
|
||||
}
|
||||
if (mkdir(result, 0700) != 0 && errno != EEXIST) {
|
||||
error:
|
||||
SDL_SetError("Couldn't create directory '%s': '%s'", result, strerror(errno));
|
||||
SDL_free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/*
|
||||
The two functions below (prefixed with `xdg_`) have been copied from:
|
||||
https://gitlab.freedesktop.org/xdg/xdg-user-dirs/-/blob/master/xdg-user-dir-lookup.c
|
||||
and have been adapted to work with SDL. They are licensed under the following
|
||||
terms:
|
||||
|
||||
Copyright (c) 2007 Red Hat, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person
|
||||
obtaining a copy of this software and associated documentation files
|
||||
(the "Software"), to deal in the Software without restriction,
|
||||
including without limitation the rights to use, copy, modify, merge,
|
||||
publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
and to permit persons to whom the Software is furnished to do so,
|
||||
subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
|
||||
BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
||||
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
static char *xdg_user_dir_lookup_with_fallback (const char *type, const char *fallback)
|
||||
{
|
||||
FILE *file;
|
||||
const char *home_dir, *config_home;
|
||||
char *config_file;
|
||||
char buffer[512];
|
||||
char *user_dir;
|
||||
char *p, *d;
|
||||
int len;
|
||||
int relative;
|
||||
size_t l;
|
||||
|
||||
home_dir = SDL_getenv("HOME");
|
||||
|
||||
if (!home_dir)
|
||||
goto error;
|
||||
|
||||
config_home = SDL_getenv("XDG_CONFIG_HOME");
|
||||
if (!config_home || config_home[0] == 0)
|
||||
{
|
||||
l = SDL_strlen (home_dir) + SDL_strlen ("/.config/user-dirs.dirs") + 1;
|
||||
config_file = (char*) SDL_malloc (l);
|
||||
if (!config_file)
|
||||
goto error;
|
||||
|
||||
SDL_strlcpy (config_file, home_dir, l);
|
||||
SDL_strlcat (config_file, "/.config/user-dirs.dirs", l);
|
||||
}
|
||||
else
|
||||
{
|
||||
l = SDL_strlen (config_home) + SDL_strlen ("/user-dirs.dirs") + 1;
|
||||
config_file = (char*) SDL_malloc (l);
|
||||
if (!config_file)
|
||||
goto error;
|
||||
|
||||
SDL_strlcpy (config_file, config_home, l);
|
||||
SDL_strlcat (config_file, "/user-dirs.dirs", l);
|
||||
}
|
||||
|
||||
file = fopen (config_file, "r");
|
||||
SDL_free (config_file);
|
||||
if (!file)
|
||||
goto error;
|
||||
|
||||
user_dir = NULL;
|
||||
while (fgets (buffer, sizeof (buffer), file))
|
||||
{
|
||||
// Remove newline at end
|
||||
len = SDL_strlen (buffer);
|
||||
if (len > 0 && buffer[len-1] == '\n')
|
||||
buffer[len-1] = 0;
|
||||
|
||||
p = buffer;
|
||||
while (*p == ' ' || *p == '\t')
|
||||
p++;
|
||||
|
||||
if (SDL_strncmp (p, "XDG_", 4) != 0)
|
||||
continue;
|
||||
p += 4;
|
||||
if (SDL_strncmp (p, type, SDL_strlen (type)) != 0)
|
||||
continue;
|
||||
p += SDL_strlen (type);
|
||||
if (SDL_strncmp (p, "_DIR", 4) != 0)
|
||||
continue;
|
||||
p += 4;
|
||||
|
||||
while (*p == ' ' || *p == '\t')
|
||||
p++;
|
||||
|
||||
if (*p != '=')
|
||||
continue;
|
||||
p++;
|
||||
|
||||
while (*p == ' ' || *p == '\t')
|
||||
p++;
|
||||
|
||||
if (*p != '"')
|
||||
continue;
|
||||
p++;
|
||||
|
||||
relative = 0;
|
||||
if (SDL_strncmp (p, "$HOME/", 6) == 0)
|
||||
{
|
||||
p += 6;
|
||||
relative = 1;
|
||||
}
|
||||
else if (*p != '/')
|
||||
continue;
|
||||
|
||||
SDL_free (user_dir);
|
||||
if (relative)
|
||||
{
|
||||
l = SDL_strlen (home_dir) + 1 + SDL_strlen (p) + 1;
|
||||
user_dir = (char*) SDL_malloc (l);
|
||||
if (!user_dir)
|
||||
goto error2;
|
||||
|
||||
SDL_strlcpy (user_dir, home_dir, l);
|
||||
SDL_strlcat (user_dir, "/", l);
|
||||
}
|
||||
else
|
||||
{
|
||||
user_dir = (char*) SDL_malloc (SDL_strlen (p) + 1);
|
||||
if (!user_dir)
|
||||
goto error2;
|
||||
|
||||
*user_dir = 0;
|
||||
}
|
||||
|
||||
d = user_dir + SDL_strlen (user_dir);
|
||||
while (*p && *p != '"')
|
||||
{
|
||||
if ((*p == '\\') && (*(p+1) != 0))
|
||||
p++;
|
||||
*d++ = *p++;
|
||||
}
|
||||
*d = 0;
|
||||
}
|
||||
error2:
|
||||
fclose (file);
|
||||
|
||||
if (user_dir)
|
||||
return user_dir;
|
||||
|
||||
error:
|
||||
if (fallback)
|
||||
return SDL_strdup (fallback);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static char *xdg_user_dir_lookup (const char *type)
|
||||
{
|
||||
const char *home_dir;
|
||||
char *dir, *user_dir;
|
||||
|
||||
dir = xdg_user_dir_lookup_with_fallback(type, NULL);
|
||||
if (dir)
|
||||
return dir;
|
||||
|
||||
home_dir = SDL_getenv("HOME");
|
||||
|
||||
if (!home_dir)
|
||||
return NULL;
|
||||
|
||||
// Special case desktop for historical compatibility
|
||||
if (SDL_strcmp(type, "DESKTOP") == 0) {
|
||||
size_t length = SDL_strlen(home_dir) + SDL_strlen("/Desktop") + 1;
|
||||
user_dir = (char*) SDL_malloc(length);
|
||||
if (!user_dir)
|
||||
return NULL;
|
||||
|
||||
SDL_strlcpy(user_dir, home_dir, length);
|
||||
SDL_strlcat(user_dir, "/Desktop", length);
|
||||
return user_dir;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetUserFolder(SDL_Folder folder)
|
||||
{
|
||||
const char *param = NULL;
|
||||
char *result;
|
||||
char *newresult;
|
||||
|
||||
/* According to `man xdg-user-dir`, the possible values are:
|
||||
DESKTOP
|
||||
DOWNLOAD
|
||||
TEMPLATES
|
||||
PUBLICSHARE
|
||||
DOCUMENTS
|
||||
MUSIC
|
||||
PICTURES
|
||||
VIDEOS
|
||||
*/
|
||||
switch(folder) {
|
||||
case SDL_FOLDER_HOME:
|
||||
param = SDL_getenv("HOME");
|
||||
|
||||
if (!param) {
|
||||
SDL_SetError("No $HOME environment variable available");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = SDL_strdup(param);
|
||||
goto append_slash;
|
||||
|
||||
case SDL_FOLDER_DESKTOP:
|
||||
param = "DESKTOP";
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_DOCUMENTS:
|
||||
param = "DOCUMENTS";
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_DOWNLOADS:
|
||||
param = "DOWNLOAD";
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_MUSIC:
|
||||
param = "MUSIC";
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_PICTURES:
|
||||
param = "PICTURES";
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_PUBLICSHARE:
|
||||
param = "PUBLICSHARE";
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_SAVEDGAMES:
|
||||
SDL_SetError("Saved Games folder unavailable on XDG");
|
||||
return NULL;
|
||||
|
||||
case SDL_FOLDER_SCREENSHOTS:
|
||||
SDL_SetError("Screenshots folder unavailable on XDG");
|
||||
return NULL;
|
||||
|
||||
case SDL_FOLDER_TEMPLATES:
|
||||
param = "TEMPLATES";
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_VIDEOS:
|
||||
param = "VIDEOS";
|
||||
break;
|
||||
|
||||
default:
|
||||
SDL_SetError("Invalid SDL_Folder: %d", (int) folder);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* param *should* to be set to something at this point, but just in case */
|
||||
if (!param) {
|
||||
SDL_SetError("No corresponding XDG user directory");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = xdg_user_dir_lookup(param);
|
||||
|
||||
if (!result) {
|
||||
SDL_SetError("XDG directory not available");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
append_slash:
|
||||
newresult = (char *) SDL_realloc(result, SDL_strlen(result) + 2);
|
||||
|
||||
if (!newresult) {
|
||||
SDL_free(result);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
result = newresult;
|
||||
SDL_strlcat(result, "/", SDL_strlen(result) + 2);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#endif // SDL_FILESYSTEM_UNIX
|
||||
92
vendor/sdl-3.2.10/src/filesystem/vita/SDL_sysfilesystem.c
vendored
Normal file
92
vendor/sdl-3.2.10/src/filesystem/vita/SDL_sysfilesystem.c
vendored
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_FILESYSTEM_VITA
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
// System dependent filesystem routines
|
||||
|
||||
#include "../SDL_sysfilesystem.h"
|
||||
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <psp2/io/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
char *SDL_SYS_GetBasePath(void)
|
||||
{
|
||||
return SDL_strdup("app0:/");
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
const char *envr = "ux0:/data/";
|
||||
char *result = NULL;
|
||||
char *ptr = NULL;
|
||||
size_t len = 0;
|
||||
|
||||
if (!app) {
|
||||
SDL_InvalidParamError("app");
|
||||
return NULL;
|
||||
}
|
||||
if (!org) {
|
||||
org = "";
|
||||
}
|
||||
|
||||
len = SDL_strlen(envr);
|
||||
|
||||
len += SDL_strlen(org) + SDL_strlen(app) + 3;
|
||||
result = (char *)SDL_malloc(len);
|
||||
if (!result) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (*org) {
|
||||
SDL_snprintf(result, len, "%s%s/%s/", envr, org, app);
|
||||
} else {
|
||||
SDL_snprintf(result, len, "%s%s/", envr, app);
|
||||
}
|
||||
|
||||
for (ptr = result + 1; *ptr; ptr++) {
|
||||
if (*ptr == '/') {
|
||||
*ptr = '\0';
|
||||
sceIoMkdir(result, 0777);
|
||||
*ptr = '/';
|
||||
}
|
||||
}
|
||||
sceIoMkdir(result, 0777);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO
|
||||
char *SDL_SYS_GetUserFolder(SDL_Folder folder)
|
||||
{
|
||||
SDL_Unsupported();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#endif // SDL_FILESYSTEM_VITA
|
||||
382
vendor/sdl-3.2.10/src/filesystem/windows/SDL_sysfilesystem.c
vendored
Normal file
382
vendor/sdl-3.2.10/src/filesystem/windows/SDL_sysfilesystem.c
vendored
Normal file
|
|
@ -0,0 +1,382 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#ifdef SDL_FILESYSTEM_WINDOWS
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
// System dependent filesystem routines
|
||||
|
||||
#include "../SDL_sysfilesystem.h"
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
#include <shlobj.h>
|
||||
#include <initguid.h>
|
||||
|
||||
// These aren't all defined in older SDKs, so define them here
|
||||
DEFINE_GUID(SDL_FOLDERID_Profile, 0x5E6C858F, 0x0E22, 0x4760, 0x9A, 0xFE, 0xEA, 0x33, 0x17, 0xB6, 0x71, 0x73);
|
||||
DEFINE_GUID(SDL_FOLDERID_Desktop, 0xB4BFCC3A, 0xDB2C, 0x424C, 0xB0, 0x29, 0x7F, 0xE9, 0x9A, 0x87, 0xC6, 0x41);
|
||||
DEFINE_GUID(SDL_FOLDERID_Documents, 0xFDD39AD0, 0x238F, 0x46AF, 0xAD, 0xB4, 0x6C, 0x85, 0x48, 0x03, 0x69, 0xC7);
|
||||
DEFINE_GUID(SDL_FOLDERID_Downloads, 0x374de290, 0x123f, 0x4565, 0x91, 0x64, 0x39, 0xc4, 0x92, 0x5e, 0x46, 0x7b);
|
||||
DEFINE_GUID(SDL_FOLDERID_Music, 0x4BD8D571, 0x6D19, 0x48D3, 0xBE, 0x97, 0x42, 0x22, 0x20, 0x08, 0x0E, 0x43);
|
||||
DEFINE_GUID(SDL_FOLDERID_Pictures, 0x33E28130, 0x4E1E, 0x4676, 0x83, 0x5A, 0x98, 0x39, 0x5C, 0x3B, 0xC3, 0xBB);
|
||||
DEFINE_GUID(SDL_FOLDERID_SavedGames, 0x4c5c32ff, 0xbb9d, 0x43b0, 0xb5, 0xb4, 0x2d, 0x72, 0xe5, 0x4e, 0xaa, 0xa4);
|
||||
DEFINE_GUID(SDL_FOLDERID_Screenshots, 0xb7bede81, 0xdf94, 0x4682, 0xa7, 0xd8, 0x57, 0xa5, 0x26, 0x20, 0xb8, 0x6f);
|
||||
DEFINE_GUID(SDL_FOLDERID_Templates, 0xA63293E8, 0x664E, 0x48DB, 0xA0, 0x79, 0xDF, 0x75, 0x9E, 0x05, 0x09, 0xF7);
|
||||
DEFINE_GUID(SDL_FOLDERID_Videos, 0x18989B1D, 0x99B5, 0x455B, 0x84, 0x1C, 0xAB, 0x7C, 0x74, 0xE4, 0xDD, 0xFC);
|
||||
|
||||
char *SDL_SYS_GetBasePath(void)
|
||||
{
|
||||
DWORD buflen = 128;
|
||||
WCHAR *path = NULL;
|
||||
char *result = NULL;
|
||||
DWORD len = 0;
|
||||
int i;
|
||||
|
||||
while (true) {
|
||||
void *ptr = SDL_realloc(path, buflen * sizeof(WCHAR));
|
||||
if (!ptr) {
|
||||
SDL_free(path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
path = (WCHAR *)ptr;
|
||||
|
||||
len = GetModuleFileNameW(NULL, path, buflen);
|
||||
// if it truncated, then len >= buflen - 1
|
||||
// if there was enough room (or failure), len < buflen - 1
|
||||
if (len < buflen - 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
// buffer too small? Try again.
|
||||
buflen *= 2;
|
||||
}
|
||||
|
||||
if (len == 0) {
|
||||
SDL_free(path);
|
||||
WIN_SetError("Couldn't locate our .exe");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
for (i = len - 1; i > 0; i--) {
|
||||
if (path[i] == '\\') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_assert(i > 0); // Should have been an absolute path.
|
||||
path[i + 1] = '\0'; // chop off filename.
|
||||
|
||||
result = WIN_StringToUTF8W(path);
|
||||
SDL_free(path);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetPrefPath(const char *org, const char *app)
|
||||
{
|
||||
/*
|
||||
* Vista and later has a new API for this, but SHGetFolderPath works there,
|
||||
* and apparently just wraps the new API. This is the new way to do it:
|
||||
*
|
||||
* SHGetKnownFolderPath(SDL_FOLDERID_RoamingAppData, KF_FLAG_CREATE,
|
||||
* NULL, &wszPath);
|
||||
*/
|
||||
|
||||
HRESULT hr = E_FAIL;
|
||||
WCHAR path[MAX_PATH];
|
||||
char *result = NULL;
|
||||
WCHAR *worg = NULL;
|
||||
WCHAR *wapp = NULL;
|
||||
size_t new_wpath_len = 0;
|
||||
BOOL api_result = FALSE;
|
||||
|
||||
if (!app) {
|
||||
SDL_InvalidParamError("app");
|
||||
return NULL;
|
||||
}
|
||||
if (!org) {
|
||||
org = "";
|
||||
}
|
||||
|
||||
hr = SHGetFolderPathW(NULL, CSIDL_APPDATA | CSIDL_FLAG_CREATE, NULL, 0, path);
|
||||
if (!SUCCEEDED(hr)) {
|
||||
WIN_SetErrorFromHRESULT("Couldn't locate our prefpath", hr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
worg = WIN_UTF8ToStringW(org);
|
||||
if (!worg) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
wapp = WIN_UTF8ToStringW(app);
|
||||
if (!wapp) {
|
||||
SDL_free(worg);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
new_wpath_len = SDL_wcslen(worg) + SDL_wcslen(wapp) + SDL_wcslen(path) + 3;
|
||||
|
||||
if ((new_wpath_len + 1) > MAX_PATH) {
|
||||
SDL_free(worg);
|
||||
SDL_free(wapp);
|
||||
WIN_SetError("Path too long.");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (*worg) {
|
||||
SDL_wcslcat(path, L"\\", SDL_arraysize(path));
|
||||
SDL_wcslcat(path, worg, SDL_arraysize(path));
|
||||
}
|
||||
SDL_free(worg);
|
||||
|
||||
api_result = CreateDirectoryW(path, NULL);
|
||||
if (api_result == FALSE) {
|
||||
if (GetLastError() != ERROR_ALREADY_EXISTS) {
|
||||
SDL_free(wapp);
|
||||
WIN_SetError("Couldn't create a prefpath.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_wcslcat(path, L"\\", SDL_arraysize(path));
|
||||
SDL_wcslcat(path, wapp, SDL_arraysize(path));
|
||||
SDL_free(wapp);
|
||||
|
||||
api_result = CreateDirectoryW(path, NULL);
|
||||
if (api_result == FALSE) {
|
||||
if (GetLastError() != ERROR_ALREADY_EXISTS) {
|
||||
WIN_SetError("Couldn't create a prefpath.");
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SDL_wcslcat(path, L"\\", SDL_arraysize(path));
|
||||
|
||||
result = WIN_StringToUTF8W(path);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetUserFolder(SDL_Folder folder)
|
||||
{
|
||||
typedef HRESULT (WINAPI *pfnSHGetKnownFolderPath)(REFGUID /* REFKNOWNFOLDERID */, DWORD, HANDLE, PWSTR*);
|
||||
HMODULE lib = LoadLibrary(L"Shell32.dll");
|
||||
pfnSHGetKnownFolderPath pSHGetKnownFolderPath = NULL;
|
||||
char *result = NULL;
|
||||
|
||||
if (lib) {
|
||||
pSHGetKnownFolderPath = (pfnSHGetKnownFolderPath)GetProcAddress(lib, "SHGetKnownFolderPath");
|
||||
}
|
||||
|
||||
if (pSHGetKnownFolderPath) {
|
||||
GUID type; // KNOWNFOLDERID
|
||||
HRESULT hr;
|
||||
wchar_t *path;
|
||||
|
||||
switch (folder) {
|
||||
case SDL_FOLDER_HOME:
|
||||
type = SDL_FOLDERID_Profile;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_DESKTOP:
|
||||
type = SDL_FOLDERID_Desktop;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_DOCUMENTS:
|
||||
type = SDL_FOLDERID_Documents;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_DOWNLOADS:
|
||||
type = SDL_FOLDERID_Downloads;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_MUSIC:
|
||||
type = SDL_FOLDERID_Music;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_PICTURES:
|
||||
type = SDL_FOLDERID_Pictures;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_PUBLICSHARE:
|
||||
SDL_SetError("Public share unavailable on Windows");
|
||||
goto done;
|
||||
|
||||
case SDL_FOLDER_SAVEDGAMES:
|
||||
type = SDL_FOLDERID_SavedGames;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_SCREENSHOTS:
|
||||
type = SDL_FOLDERID_Screenshots;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_TEMPLATES:
|
||||
type = SDL_FOLDERID_Templates;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_VIDEOS:
|
||||
type = SDL_FOLDERID_Videos;
|
||||
break;
|
||||
|
||||
default:
|
||||
SDL_SetError("Invalid SDL_Folder: %d", (int)folder);
|
||||
goto done;
|
||||
};
|
||||
|
||||
hr = pSHGetKnownFolderPath(&type, 0x00008000 /* KF_FLAG_CREATE */, NULL, &path);
|
||||
if (SUCCEEDED(hr)) {
|
||||
result = WIN_StringToUTF8W(path);
|
||||
} else {
|
||||
WIN_SetErrorFromHRESULT("Couldn't get folder", hr);
|
||||
}
|
||||
|
||||
} else {
|
||||
int type;
|
||||
HRESULT hr;
|
||||
wchar_t path[MAX_PATH];
|
||||
|
||||
switch (folder) {
|
||||
case SDL_FOLDER_HOME:
|
||||
type = CSIDL_PROFILE;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_DESKTOP:
|
||||
type = CSIDL_DESKTOP;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_DOCUMENTS:
|
||||
type = CSIDL_MYDOCUMENTS;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_DOWNLOADS:
|
||||
SDL_SetError("Downloads folder unavailable before Vista");
|
||||
goto done;
|
||||
|
||||
case SDL_FOLDER_MUSIC:
|
||||
type = CSIDL_MYMUSIC;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_PICTURES:
|
||||
type = CSIDL_MYPICTURES;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_PUBLICSHARE:
|
||||
SDL_SetError("Public share unavailable on Windows");
|
||||
goto done;
|
||||
|
||||
case SDL_FOLDER_SAVEDGAMES:
|
||||
SDL_SetError("Saved games unavailable before Vista");
|
||||
goto done;
|
||||
|
||||
case SDL_FOLDER_SCREENSHOTS:
|
||||
SDL_SetError("Screenshots folder unavailable before Vista");
|
||||
goto done;
|
||||
|
||||
case SDL_FOLDER_TEMPLATES:
|
||||
type = CSIDL_TEMPLATES;
|
||||
break;
|
||||
|
||||
case SDL_FOLDER_VIDEOS:
|
||||
type = CSIDL_MYVIDEO;
|
||||
break;
|
||||
|
||||
default:
|
||||
SDL_SetError("Unsupported SDL_Folder on Windows before Vista: %d", (int)folder);
|
||||
goto done;
|
||||
};
|
||||
|
||||
// Create the OS-specific folder if it doesn't already exist
|
||||
type |= CSIDL_FLAG_CREATE;
|
||||
|
||||
#if 0
|
||||
// Apparently the oldest, but not supported in modern Windows
|
||||
HRESULT hr = SHGetSpecialFolderPath(NULL, path, type, TRUE);
|
||||
#endif
|
||||
|
||||
/* Windows 2000/XP and later, deprecated as of Windows 10 (still
|
||||
available), available in Wine (tested 6.0.3) */
|
||||
hr = SHGetFolderPathW(NULL, type, NULL, SHGFP_TYPE_CURRENT, path);
|
||||
|
||||
// use `== TRUE` for SHGetSpecialFolderPath
|
||||
if (SUCCEEDED(hr)) {
|
||||
result = WIN_StringToUTF8W(path);
|
||||
} else {
|
||||
WIN_SetErrorFromHRESULT("Couldn't get folder", hr);
|
||||
}
|
||||
}
|
||||
|
||||
if (result) {
|
||||
char *newresult = (char *) SDL_realloc(result, SDL_strlen(result) + 2);
|
||||
|
||||
if (!newresult) {
|
||||
SDL_free(result);
|
||||
result = NULL; // will be returned
|
||||
goto done;
|
||||
}
|
||||
|
||||
result = newresult;
|
||||
SDL_strlcat(result, "\\", SDL_strlen(result) + 2);
|
||||
}
|
||||
|
||||
done:
|
||||
if (lib) {
|
||||
FreeLibrary(lib);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
char *SDL_SYS_GetCurrentDirectory(void)
|
||||
{
|
||||
WCHAR *wstr = NULL;
|
||||
DWORD buflen = 0;
|
||||
while (true) {
|
||||
const DWORD bw = GetCurrentDirectoryW(buflen, wstr);
|
||||
if (bw == 0) {
|
||||
WIN_SetError("GetCurrentDirectoryW failed");
|
||||
return NULL;
|
||||
} else if (bw < buflen) { // we got it!
|
||||
// make sure there's a path separator at the end.
|
||||
SDL_assert(bw < (buflen + 2));
|
||||
if ((bw == 0) || (wstr[bw-1] != '\\')) {
|
||||
wstr[bw] = '\\';
|
||||
wstr[bw + 1] = '\0';
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
void *ptr = SDL_realloc(wstr, (bw + 1) * sizeof (WCHAR));
|
||||
if (!ptr) {
|
||||
SDL_free(wstr);
|
||||
return NULL;
|
||||
}
|
||||
wstr = (WCHAR *) ptr;
|
||||
buflen = bw;
|
||||
}
|
||||
|
||||
char *retval = WIN_StringToUTF8W(wstr);
|
||||
SDL_free(wstr);
|
||||
return retval;
|
||||
}
|
||||
|
||||
#endif // SDL_FILESYSTEM_WINDOWS
|
||||
231
vendor/sdl-3.2.10/src/filesystem/windows/SDL_sysfsops.c
vendored
Normal file
231
vendor/sdl-3.2.10/src/filesystem/windows/SDL_sysfsops.c
vendored
Normal file
|
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
Simple DirectMedia Layer
|
||||
Copyright (C) 1997-2025 Sam Lantinga <slouken@libsdl.org>
|
||||
|
||||
This software is provided 'as-is', without any express or implied
|
||||
warranty. In no event will the authors be held liable for any damages
|
||||
arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose,
|
||||
including commercial applications, and to alter it and redistribute it
|
||||
freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not
|
||||
claim that you wrote the original software. If you use this software
|
||||
in a product, an acknowledgment in the product documentation would be
|
||||
appreciated but is not required.
|
||||
2. Altered source versions must be plainly marked as such, and must not be
|
||||
misrepresented as being the original software.
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
*/
|
||||
|
||||
#include "SDL_internal.h"
|
||||
|
||||
#if defined(SDL_FSOPS_WINDOWS)
|
||||
|
||||
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
|
||||
// System dependent filesystem routines
|
||||
|
||||
#include "../../core/windows/SDL_windows.h"
|
||||
#include "../SDL_sysfilesystem.h"
|
||||
|
||||
bool SDL_SYS_EnumerateDirectory(const char *path, SDL_EnumerateDirectoryCallback cb, void *userdata)
|
||||
{
|
||||
SDL_EnumerationResult result = SDL_ENUM_CONTINUE;
|
||||
if (*path == '\0') { // if empty (completely at the root), we need to enumerate drive letters.
|
||||
const DWORD drives = GetLogicalDrives();
|
||||
char name[] = { 0, ':', '\\', '\0' };
|
||||
for (int i = 'A'; (result == SDL_ENUM_CONTINUE) && (i <= 'Z'); i++) {
|
||||
if (drives & (1 << (i - 'A'))) {
|
||||
name[0] = (char) i;
|
||||
result = cb(userdata, "", name);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// you need a wildcard to enumerate through FindFirstFileEx(), but the wildcard is only checked in the
|
||||
// filename element at the end of the path string, so always tack on a "\\*" to get everything, and
|
||||
// also prevent any wildcards inserted by the app from being respected.
|
||||
char *pattern = NULL;
|
||||
int patternlen = SDL_asprintf(&pattern, "%s\\\\", path); // we'll replace that second '\\' in the trimdown.
|
||||
if ((patternlen == -1) || (!pattern)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// trim down to a single path separator at the end, in case the caller added one or more.
|
||||
patternlen--;
|
||||
while ((patternlen >= 0) && ((pattern[patternlen] == '\\') || (pattern[patternlen] == '/'))) {
|
||||
pattern[patternlen--] ='\0';
|
||||
}
|
||||
pattern[++patternlen] = '\\';
|
||||
pattern[++patternlen] = '*';
|
||||
pattern[++patternlen] = '\0';
|
||||
|
||||
WCHAR *wpattern = WIN_UTF8ToStringW(pattern);
|
||||
if (!wpattern) {
|
||||
SDL_free(pattern);
|
||||
return false;
|
||||
}
|
||||
|
||||
pattern[--patternlen] = '\0'; // chop off the '*' so we just have the dirname with a path separator.
|
||||
|
||||
WIN32_FIND_DATAW entw;
|
||||
HANDLE dir = FindFirstFileExW(wpattern, FindExInfoStandard, &entw, FindExSearchNameMatch, NULL, 0);
|
||||
SDL_free(wpattern);
|
||||
if (dir == INVALID_HANDLE_VALUE) {
|
||||
SDL_free(pattern);
|
||||
return WIN_SetError("Failed to enumerate directory");
|
||||
}
|
||||
|
||||
do {
|
||||
const WCHAR *fn = entw.cFileName;
|
||||
|
||||
if (fn[0] == '.') { // ignore "." and ".."
|
||||
if ((fn[1] == '\0') || ((fn[1] == '.') && (fn[2] == '\0'))) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
char *utf8fn = WIN_StringToUTF8W(fn);
|
||||
if (!utf8fn) {
|
||||
result = SDL_ENUM_FAILURE;
|
||||
} else {
|
||||
result = cb(userdata, pattern, utf8fn);
|
||||
SDL_free(utf8fn);
|
||||
}
|
||||
} while ((result == SDL_ENUM_CONTINUE) && (FindNextFileW(dir, &entw) != 0));
|
||||
|
||||
FindClose(dir);
|
||||
SDL_free(pattern);
|
||||
}
|
||||
|
||||
return (result != SDL_ENUM_FAILURE);
|
||||
}
|
||||
|
||||
bool SDL_SYS_RemovePath(const char *path)
|
||||
{
|
||||
WCHAR *wpath = WIN_UTF8ToStringW(path);
|
||||
if (!wpath) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WIN32_FILE_ATTRIBUTE_DATA info;
|
||||
if (!GetFileAttributesExW(wpath, GetFileExInfoStandard, &info)) {
|
||||
SDL_free(wpath);
|
||||
if (GetLastError() == ERROR_FILE_NOT_FOUND) {
|
||||
// Note that ERROR_PATH_NOT_FOUND means a parent dir is missing, and we consider that an error.
|
||||
return true; // thing is already gone, call it a success.
|
||||
}
|
||||
return WIN_SetError("Couldn't get path's attributes");
|
||||
}
|
||||
|
||||
const int isdir = (info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY);
|
||||
const BOOL rc = isdir ? RemoveDirectoryW(wpath) : DeleteFileW(wpath);
|
||||
SDL_free(wpath);
|
||||
if (!rc) {
|
||||
return WIN_SetError("Couldn't remove path");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDL_SYS_RenamePath(const char *oldpath, const char *newpath)
|
||||
{
|
||||
WCHAR *woldpath = WIN_UTF8ToStringW(oldpath);
|
||||
if (!woldpath) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WCHAR *wnewpath = WIN_UTF8ToStringW(newpath);
|
||||
if (!wnewpath) {
|
||||
SDL_free(woldpath);
|
||||
return false;
|
||||
}
|
||||
|
||||
const BOOL rc = MoveFileExW(woldpath, wnewpath, MOVEFILE_REPLACE_EXISTING);
|
||||
SDL_free(wnewpath);
|
||||
SDL_free(woldpath);
|
||||
if (!rc) {
|
||||
return WIN_SetError("Couldn't rename path");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDL_SYS_CopyFile(const char *oldpath, const char *newpath)
|
||||
{
|
||||
WCHAR *woldpath = WIN_UTF8ToStringW(oldpath);
|
||||
if (!woldpath) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WCHAR *wnewpath = WIN_UTF8ToStringW(newpath);
|
||||
if (!wnewpath) {
|
||||
SDL_free(woldpath);
|
||||
return false;
|
||||
}
|
||||
|
||||
const BOOL rc = CopyFileExW(woldpath, wnewpath, NULL, NULL, NULL, COPY_FILE_ALLOW_DECRYPTED_DESTINATION|COPY_FILE_NO_BUFFERING);
|
||||
SDL_free(wnewpath);
|
||||
SDL_free(woldpath);
|
||||
if (!rc) {
|
||||
return WIN_SetError("Couldn't copy path");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDL_SYS_CreateDirectory(const char *path)
|
||||
{
|
||||
WCHAR *wpath = WIN_UTF8ToStringW(path);
|
||||
if (!wpath) {
|
||||
return false;
|
||||
}
|
||||
|
||||
DWORD rc = CreateDirectoryW(wpath, NULL);
|
||||
if (!rc && (GetLastError() == ERROR_ALREADY_EXISTS)) {
|
||||
WIN32_FILE_ATTRIBUTE_DATA winstat;
|
||||
if (GetFileAttributesExW(wpath, GetFileExInfoStandard, &winstat)) {
|
||||
if (winstat.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
rc = 1; // exists and is already a directory: cool.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SDL_free(wpath);
|
||||
if (!rc) {
|
||||
return WIN_SetError("Couldn't create directory");
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SDL_SYS_GetPathInfo(const char *path, SDL_PathInfo *info)
|
||||
{
|
||||
WCHAR *wpath = WIN_UTF8ToStringW(path);
|
||||
if (!wpath) {
|
||||
return false;
|
||||
}
|
||||
|
||||
WIN32_FILE_ATTRIBUTE_DATA winstat;
|
||||
const BOOL rc = GetFileAttributesExW(wpath, GetFileExInfoStandard, &winstat);
|
||||
SDL_free(wpath);
|
||||
if (!rc) {
|
||||
return WIN_SetError("Can't stat");
|
||||
}
|
||||
|
||||
if (winstat.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
|
||||
info->type = SDL_PATHTYPE_DIRECTORY;
|
||||
info->size = 0;
|
||||
} else if (winstat.dwFileAttributes & (FILE_ATTRIBUTE_OFFLINE | FILE_ATTRIBUTE_DEVICE)) {
|
||||
info->type = SDL_PATHTYPE_OTHER;
|
||||
info->size = ((((Uint64) winstat.nFileSizeHigh) << 32) | winstat.nFileSizeLow);
|
||||
} else {
|
||||
info->type = SDL_PATHTYPE_FILE;
|
||||
info->size = ((((Uint64) winstat.nFileSizeHigh) << 32) | winstat.nFileSizeLow);
|
||||
}
|
||||
|
||||
info->create_time = SDL_TimeFromWindows(winstat.ftCreationTime.dwLowDateTime, winstat.ftCreationTime.dwHighDateTime);
|
||||
info->modify_time = SDL_TimeFromWindows(winstat.ftLastWriteTime.dwLowDateTime, winstat.ftLastWriteTime.dwHighDateTime);
|
||||
info->access_time = SDL_TimeFromWindows(winstat.ftLastAccessTime.dwLowDateTime, winstat.ftLastAccessTime.dwHighDateTime);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
#endif // SDL_FSOPS_WINDOWS
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue