From 015390a51e7740e5776f0eda29a6a11edcd0b0ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Robert=20M=C3=BCller?= Date: Sat, 23 Mar 2024 20:39:52 +0100 Subject: [PATCH] Fix recursive folder creation with mixed slashes and drive letters The function `fs_makedir_rec_for` for recursively creating folders did not handle paths containing backslashes correctly and only created folders after every occurrence of a regular slash. This could cause the recursive folder creation to fail when a parent folder is not created before the child folder. For example when recursively creating folders for the path `D:\Games/DDNet\downloadedskins`, the `DDNet` folder was not being created because this path segment does not end in a forward slash. Now, backslashes are handled the same as regular slashes, which is consistent with the other filesystem functions. Additionally, the function tried to create folders for drive letters on Windows (e.g. `C:` and `D:`). Trying to create a system drive as a folder will fail due to access being denied, whereas it seems to work for already existing non-system drives. For example when recursively creating folders for the path `C:/Games/DDNet/downloadedskins`, the `C:` "folder" could not be created which caused the entire operation to fail. Now, the function will not try to create folders for drive letters anymore, i.e. if the name of the to be created folder ends with `:`. Closes #8148. --- src/base/system.cpp | 15 +++++++++------ src/base/system.h | 4 ++-- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/base/system.cpp b/src/base/system.cpp index 79e712af8..3d97b3fef 100644 --- a/src/base/system.cpp +++ b/src/base/system.cpp @@ -2293,17 +2293,20 @@ int fs_storage_path(const char *appname, char *path, int max) int fs_makedir_rec_for(const char *path) { - char buffer[1024 * 2]; - char *p; + char buffer[IO_MAX_PATH_LENGTH]; str_copy(buffer, path); - for(p = buffer + 1; *p != '\0'; p++) + for(int index = 1; buffer[index] != '\0'; ++index) { - if(*p == '/' && *(p + 1) != '\0') + // Do not try to create folder for drive letters on Windows, + // as this is not necessary and may fail for system drives. + if((buffer[index] == '/' || buffer[index] == '\\') && buffer[index + 1] != '\0' && buffer[index - 1] != ':') { - *p = '\0'; + buffer[index] = '\0'; if(fs_makedir(buffer) < 0) + { return -1; - *p = '/'; + } + buffer[index] = '/'; } } return 0; diff --git a/src/base/system.h b/src/base/system.h index d7425a512..85127f112 100644 --- a/src/base/system.h +++ b/src/base/system.h @@ -1839,11 +1839,11 @@ int fs_makedir(const char *path); int fs_removedir(const char *path); /** - * Recursively create directories for a file. + * Recursively creates parent directories for a file or directory. * * @ingroup Filesystem * - * @param path - File for which to create directories. + * @param path File or directory for which to create parent directories. * * @return 0 on success. Negative value on failure. *