win32/rmdir_r.cpp: Check directory exists beforehand

rmdir_r's POSIX counterpart returns 0 on non-existing directories.
However, when SHFileOperation is called on a non-existing directory,
usually with DE_INVALIDFILES (0x7C) as its return code, although it is
considered unreliable. [1] Therefore, its existence must be checked
first.

[1]: https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shfileoperationa
This commit is contained in:
Xavier Del Campo Romero 2025-01-09 21:56:13 +01:00
parent bb48d6a4dc
commit 709f34eddc
Signed by: xavi
GPG key ID: 84FF3612A9BF43F2
2 changed files with 13 additions and 2 deletions

View file

@ -25,6 +25,10 @@ ENDIF(WIN32)
# Note: Headers needed for having them available in IDEs. # Note: Headers needed for having them available in IDEs.
SD_ADD_LIBRARY(portability SHARED ${PORTABILITY_SOURCES} ${PORTABILITY_HEADERS}) SD_ADD_LIBRARY(portability SHARED ${PORTABILITY_SOURCES} ${PORTABILITY_HEADERS})
IF(WIN32)
TARGET_LINK_LIBRARIES(portability shlwapi)
ENDIF()
target_include_directories(portability PUBLIC target_include_directories(portability PUBLIC
${CMAKE_BINARY_DIR} ${CMAKE_BINARY_DIR}
${CMAKE_CURRENT_LIST_DIR} ${CMAKE_CURRENT_LIST_DIR}

View file

@ -13,10 +13,12 @@
#include <windows.h> #include <windows.h>
#include <winerror.h> #include <winerror.h>
#include <shlwapi.h>
#include <shellapi.h> #include <shellapi.h>
#include <cerrno> #include <cerrno>
#include <cstddef> #include <cstddef>
#include <cstdlib> #include <cstdlib>
#include <cstdint>
#include <cstdio> #include <cstdio>
#include <cstring> #include <cstring>
@ -45,10 +47,15 @@ failure:
int portability::rmdir_r(const char *path) int portability::rmdir_r(const char *path)
{ {
int ret = -1, res; int ret = -1, res;
char *dir = getdir(path);
SHFILEOPSTRUCT op = {0}; SHFILEOPSTRUCT op = {0};
char *dir = nullptr;
if (!dir) if (!PathFileExistsA(path))
{
ret = 0;
goto end;
}
else if (!(dir = getdir(path)))
{ {
fprintf(stderr, "%s: getdir failed\n", __func__); fprintf(stderr, "%s: getdir failed\n", __func__);
goto end; goto end;