-
Notifications
You must be signed in to change notification settings - Fork 286
Add support of RemoveDirectoryOptions::RemoveReadOnlyDirectory which remove read-only directories #617
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
base: master
Are you sure you want to change the base?
Add support of RemoveDirectoryOptions::RemoveReadOnlyDirectory which remove read-only directories #617
Changes from all commits
91325d3
a7cb913
5ec79ed
8dc3608
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||
|---|---|---|---|---|
|
|
@@ -200,6 +200,8 @@ enum class RemoveDirectoryOptions | |||
| None = 0, | ||||
| KeepRootDirectory = 0x1, | ||||
| RemoveReadOnly = 0x2, | ||||
| RemoveReadOnlyFile = RemoveReadOnly, | ||||
| RemoveReadOnlyDirectory = 0x4, | ||||
| }; | ||||
| DEFINE_ENUM_FLAG_OPERATORS(RemoveDirectoryOptions); | ||||
|
|
||||
|
|
@@ -315,9 +317,9 @@ inline HRESULT RemoveDirectoryRecursiveNoThrow( | |||
| // Try a DeleteFile. Some errors may be recoverable. | ||||
| if (!::DeleteFileW(pathToDelete.get())) | ||||
| { | ||||
| // Fail for anything other than ERROR_ACCESS_DENIED with option to RemoveReadOnly available | ||||
| // Fail for anything other than ERROR_ACCESS_DENIED with option to RemoveReadOnlyFile available | ||||
| bool potentiallyFixableReadOnlyProblem = | ||||
| WI_IsFlagSet(options, RemoveDirectoryOptions::RemoveReadOnly) && ::GetLastError() == ERROR_ACCESS_DENIED; | ||||
| WI_IsFlagSet(options, RemoveDirectoryOptions::RemoveReadOnlyFile) && ::GetLastError() == ERROR_ACCESS_DENIED; | ||||
| RETURN_LAST_ERROR_IF(!potentiallyFixableReadOnlyProblem); | ||||
|
|
||||
| // Fail if the file does not have read-only set, likely just an ACL problem | ||||
|
|
@@ -378,7 +380,29 @@ inline HRESULT RemoveDirectoryRecursiveNoThrow( | |||
| } | ||||
| else | ||||
| { | ||||
| RETURN_IF_WIN32_BOOL_FALSE(::RemoveDirectoryW(path.get())); | ||||
| // Try a RemoveDirectory. Some errors may be recoverable. | ||||
| if (!::RemoveDirectoryW(path.get())) | ||||
| { | ||||
| // Fail for anything other than ERROR_ACCESS_DENIED with option to RemoveReadOnlyDirectory available | ||||
| bool potentiallyFixableReadOnlyProblem = | ||||
| WI_IsFlagSet(options, RemoveDirectoryOptions::RemoveReadOnlyDirectory) && ::GetLastError() == ERROR_ACCESS_DENIED; | ||||
| RETURN_LAST_ERROR_IF(!potentiallyFixableReadOnlyProblem); | ||||
|
|
||||
| // Fail if the directory does not have read-only set, likely just an ACL problem | ||||
| DWORD directoryAttr = ::GetFileAttributesW(path.get()); | ||||
| RETURN_LAST_ERROR_IF(!WI_IsFlagSet(directoryAttr, FILE_ATTRIBUTE_READONLY)); | ||||
|
|
||||
| // Remove read-only flag, setting to NORMAL if completely empty | ||||
| WI_ClearFlag(directoryAttr, FILE_ATTRIBUTE_READONLY); | ||||
| if (directoryAttr == 0) | ||||
| { | ||||
| directoryAttr = FILE_ATTRIBUTE_DIRECTORY; | ||||
| } | ||||
|
Comment on lines
+397
to
+400
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Is this necessary? Presumably the attributes have
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Followed similar approach as when file is deleted: Line 328 in 2edb790
Set
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The difference here is that this is a directory - it must have That said, this isn't harmful, just an unnecessary check. |
||||
|
|
||||
| // Set the new attributes and try to delete the directory again, returning any failure | ||||
| ::SetFileAttributesW(path.get(), directoryAttr); | ||||
| RETURN_IF_WIN32_BOOL_FALSE(::RemoveDirectoryW(path.get())); | ||||
| } | ||||
| } | ||||
| } | ||||
| return S_OK; | ||||
|
|
||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Presumably
GetLastErrorwon't contain failure because you just calledGetFileAttributesWright before this (which probably succeeded). And even if it did fail, you probably want the original error from the call toRemoveDirectoryWThere was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Followed the similar approach for file deletion:
wil/include/wil/filesystem.h
Line 325 in 2edb790
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
IMO that seems like a bug for that code path as well.
potentiallyFixableReadOnlyProblemshould logically be something more like: