Skip to content

windows.DeleteFile Does not fail on non-empty directories #15315

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
xEgoist opened this issue Apr 16, 2023 · 2 comments · Fixed by #15316
Closed

windows.DeleteFile Does not fail on non-empty directories #15315

xEgoist opened this issue Apr 16, 2023 · 2 comments · Fixed by #15316
Labels
bug Observed behavior contradicts documented or intended behavior

Comments

@xEgoist
Copy link
Contributor

xEgoist commented Apr 16, 2023

Zig Version

0.11.0-dev.2613+b42562be7

Steps to Reproduce and Observed Behavior

Upon reading this unrelated issue: dokan-dev/dokany#883,
I learned that calling NtCreateFile with FILE_DELETE_ON_CLOSE does not fail on non-empty directories, but simply mark it as DELETE_PENDING with a success NTSTATUS.

Here are simple steps to reproduce this bug:

1- Create any folder, here i am using C:\example
2- Create any empty file inside it C:\example\test.txt

run the following:

const std = @import("std");

pub fn main() !void {
    var fd = try std.fs.openDirAbsolute("C:\\", .{});
    defer fd.close();
    try fd.deleteDir("example");
}

deleteDir will not complain and the folder will not be removed, which is not what the docs says here

Expected Behavior

DIRECTORY_NOT_EMPTY/error.DirNotEmpty should be returned.


Side Note: I am mostly guessing here, and haven't looked deeply in the changes, but I think that the recent CI timeouts #14948 are caused by windows.OpenFile infinite looping through DELETE_PENDING due to this (again, i could definately be wrong here).

zig/lib/std/os/windows.zig

Lines 141 to 156 in 23ac4dd

.USER_MAPPED_FILE => return error.AccessDenied,
.INVALID_HANDLE => unreachable,
.DELETE_PENDING => {
// This error means that there *was* a file in this location on
// the file system, but it was deleted. However, the OS is not
// finished with the deletion operation, and so this CreateFile
// call has failed. There is not really a sane way to handle
// this other than retrying the creation after the OS finishes
// the deletion.
std.time.sleep(std.time.ns_per_ms);
continue;
},
else => return unexpectedStatus(rc),
}
}
}


Solution/Alternative Delete Functions

I explored few solutions to resolve this bug to find out how other delete functions works:

  • kernel32!RemoveDirectory() returns false and sets the last error to 145 - Directory not empty. I haven't traced it, but i assume it calls SetInformationFile.
  • ntdll!NtDeleteFile Marks for deletion and silently fails as well (There is some controversy if it just sets FILE_DELETE_ON_CLOSE ).
  • Open for deletion + ntdll!NtSetInformationFile with FileDispositionInformation: this marks it for deletion and reports if not-empty.
@xEgoist xEgoist added the bug Observed behavior contradicts documented or intended behavior label Apr 16, 2023
@squeek502
Copy link
Collaborator

squeek502 commented Apr 16, 2023

Duplicate of #5537

Also relevant: #6452

@Vexu Vexu closed this as completed Apr 16, 2023
@xEgoist
Copy link
Contributor Author

xEgoist commented Apr 16, 2023

Duplicate of #5537

Also relevant: #6452

I apologize for not doing a better search. Thanks for pointing that out.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Observed behavior contradicts documented or intended behavior
Projects
None yet
Development

Successfully merging a pull request may close this issue.

3 participants