filesystem: SDL_CreateDirectory should make parent directories.

Fixes #10502.
This commit is contained in:
Ryan C. Gordon
2024-09-27 15:27:55 -04:00
parent 94030131de
commit 428f2f35be
2 changed files with 57 additions and 3 deletions

View File

@@ -249,7 +249,12 @@ typedef Uint32 SDL_GlobFlags;
#define SDL_GLOB_CASEINSENSITIVE (1u << 0)
/**
* Create a directory.
* Create a directory, and any missing parent directories.
*
* This reports success if `path` already exists as a directory.
*
* If parent directories are missing, it will also create them. Note that
* if this fails, it will not remove any parent directories it already made.
*
* \param path the path of the directory to create.
* \returns true on success or false on failure; call SDL_GetError() for more

View File

@@ -55,11 +55,60 @@ bool SDL_CopyFile(const char *oldpath, const char *newpath)
bool SDL_CreateDirectory(const char *path)
{
// TODO: Recursively create subdirectories
if (!path) {
return SDL_InvalidParamError("path");
}
return SDL_SYS_CreateDirectory(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 == '/');
#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)