Signed-off-by: Daniel Lehman dlehman25@gmail.com
--- needed by std::filesystem::remove_all, which removes files with: - CreateFileW - SetFileInformationByHandle(FileDispositionInfoEx) // currently unimplemented - SetFileInformationByHandle(FileDispositionInfo) - DeleteFile = TRUE - CloseHandle
--- dlls/ntdll/tests/file.c | 3 --- server/fd.c | 34 ++++++++++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 3 deletions(-)
diff --git a/dlls/ntdll/tests/file.c b/dlls/ntdll/tests/file.c index 31c18454f0..1d0682a633 100644 --- a/dlls/ntdll/tests/file.c +++ b/dlls/ntdll/tests/file.c @@ -3185,17 +3185,14 @@ todo_wine CloseHandle( handle2 ); fdi.DoDeleteFile = TRUE; res = pNtSetInformationFile( handle, &io, &fdi, sizeof fdi, FileDispositionInformation ); - todo_wine ok( res == STATUS_DIRECTORY_NOT_EMPTY, "unexpected FileDispositionInformation result (expected STATUS_DIRECTORY_NOT_EMPTY, got %x)\n", res ); fileDeleted = DeleteFileA( buffer ); ok( fileDeleted, "File should have been deleted\n" ); buffer[dirpos] = '\0'; CloseHandle( handle ); fileDeleted = GetFileAttributesA( buffer ) == INVALID_FILE_ATTRIBUTES && GetLastError() == ERROR_FILE_NOT_FOUND; - todo_wine ok( !fileDeleted, "Directory shouldn't have been deleted\n" ); fileDeleted = RemoveDirectoryA( buffer ); -todo_wine ok( fileDeleted, "Directory should have been deleted\n" ); }
diff --git a/server/fd.c b/server/fd.c index 39fb419f25..db1559865b 100644 --- a/server/fd.c +++ b/server/fd.c @@ -93,6 +93,9 @@ #ifdef HAVE_SYS_SYSCALL_H #include <sys/syscall.h> #endif +#ifdef HAVE_DIRENT_H +#include <dirent.h> +#endif
#include "ntstatus.h" #define WIN32_NO_STATUS @@ -2359,6 +2362,37 @@ static void set_fd_disposition( struct fd *fd, int unlink ) return; }
+#ifdef HAVE_DIRENT_H + /* can't remove non-empty directories */ + if (unlink && S_ISDIR(st.st_mode)) + { + DIR *dir; + int empty; + struct dirent *de; + + if (!(dir = fdopendir( fd->unix_fd ))) + { + file_set_error(); + return; + } + + empty = 1; + while ((de = readdir( dir ))) + { + if (!strcmp( de->d_name, "." ) || !strcmp( de->d_name, ".." )) continue; + empty = 0; + break; + } + closedir( dir ); + + if (!empty) + { + set_error( STATUS_DIRECTORY_NOT_EMPTY ); + return; + } + } +#endif + fd->closed->unlink = unlink ? 1 : 0; if (fd->options & FILE_DELETE_ON_CLOSE) fd->closed->unlink = -1;