Skip to content

Commit

Permalink
fix: consider readonly files when deleting directories (#863)
Browse files Browse the repository at this point in the history
* #849 - Implementing directory validation for ReadOnly files when trying to delete directory recursively

* Removing unnecessary lock in methods
  • Loading branch information
VictorLlanir authored Jul 15, 2022
1 parent ca6a712 commit fc2d041
Show file tree
Hide file tree
Showing 2 changed files with 30 additions and 3 deletions.
15 changes: 12 additions & 3 deletions src/System.IO.Abstractions.TestingHelpers/MockFileSystem.cs
Original file line number Diff line number Diff line change
Expand Up @@ -176,8 +176,7 @@ public void AddDirectory(string path)

lock (files)
{
if (FileExists(fixedPath) &&
(GetFile(fixedPath).Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
if (FileExists(fixedPath) && FileIsReadOnly(fixedPath))
{
throw CommonExceptions.AccessDenied(fixedPath);
}
Expand Down Expand Up @@ -302,7 +301,7 @@ public void RemoveFile(string path)

lock (files)
{
if (FileExists(path) && (GetFile(path).Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly)
if (FileExists(path) && (FileIsReadOnly(path) || Directory.Exists(path) && AnyFileIsReadOnly(path)))
{
throw CommonExceptions.AccessDenied(path);
}
Expand Down Expand Up @@ -375,6 +374,11 @@ public IEnumerable<string> AllDirectories
}
}

private bool AnyFileIsReadOnly(string path)
{
return Directory.GetFiles(path).Any(file => FileIsReadOnly(file));
}

private bool IsStartOfAnotherPath(string path)
{
return AllPaths.Any(otherPath => otherPath.StartsWith(path) && otherPath != path);
Expand All @@ -396,6 +400,11 @@ private bool DirectoryExistsWithoutFixingPath(string path)
}
}

private bool FileIsReadOnly(string path)
{
return (GetFile(path).Attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly;
}

[Serializable]
private class FileSystemEntry
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -401,6 +401,24 @@ public void MockFileSystem_FileSystemWatcher_Can_Be_Overridden()
Assert.AreEqual(path, watcher.Path);
}

[Test]
public void MockFileSystem_DeleteDirectoryRecursive_WithReadOnlyFile_ShouldThrowUnauthorizedException()
{
string baseDirectory = XFS.Path(@"C:\Test");
string textFile = XFS.Path(@"C:\Test\file.txt");

var fileSystem = new MockFileSystem();
fileSystem.AddFile(baseDirectory, new MockFileData(string.Empty));
fileSystem.AddFile(textFile, new MockFileData("Content"));
fileSystem.File.SetAttributes(textFile, FileAttributes.ReadOnly);

TestDelegate action = () => fileSystem.Directory.Delete(baseDirectory, true);

Assert.Throws<UnauthorizedAccessException>(action);
Assert.True(fileSystem.File.Exists(textFile));
Assert.True(fileSystem.Directory.Exists(baseDirectory));
}

private class TestFileSystem : MockFileSystem
{
private readonly IFileSystemWatcherFactory fileSystemWatcherFactory;
Expand Down

0 comments on commit fc2d041

Please sign in to comment.