using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace PortingAssistant.Client.Common.Utils
{
public static class FileSystemAccess
{
private static readonly string[] fileTypesToCheck = { ".csproj", ".cs", ".vbproj", ".vb" };
///
/// Checks directory and all content for write access
///
/// Directory path
/// List of items without write access
public static List CheckWriteAccessForDirectory(string path)
{
var result = (Directory.GetFiles(path)
.Where(file => fileTypesToCheck.Contains(Path.GetExtension(file)))
.Where(file => !CanWriteFile(file))).ToList();
foreach (string subDirectory in Directory.GetDirectories(path))
{
if (!CanWriteToDirectory(subDirectory))
{
result.Add(subDirectory);
}
result.AddRange(CheckWriteAccessForDirectory(subDirectory));
}
return result;
}
///
/// Checks project file and at least one file is writable
///
/// Project file path
/// True if csproj and at least one .cs file is writable
public static bool CheckWriteAccessForProject(string projectFilePath)
{
return CanWriteFile(projectFilePath) &&
DirectoryHasWriteableCSharpFile(Path.GetDirectoryName(projectFilePath));
}
private static bool DirectoryHasWriteableCSharpFile(string directoryPath)
{
if (string.IsNullOrEmpty(directoryPath))
{
return false;
}
bool fileFound = Directory.GetFiles(directoryPath)
.Where(file => fileTypesToCheck.Contains(Path.GetExtension(file)))
.Any(file => CanWriteFile(file));
return fileFound ||
Directory.GetDirectories(directoryPath).Any(subDirectory => DirectoryHasWriteableCSharpFile(subDirectory));
}
private static bool CanWriteFile(string filePath)
{
try
{
using var fs = File.Open(filePath, FileMode.Open, FileAccess.Write);
return fs.CanWrite;
}
catch (System.UnauthorizedAccessException)
{
return false;
}
}
private static bool CanWriteToDirectory(string directoryPath)
{
try
{
using FileStream fs = File.Create(
Path.Combine(directoryPath, Path.GetRandomFileName()),
1,
FileOptions.DeleteOnClose);
return true;
}
catch (System.UnauthorizedAccessException)
{
return false;
}
}
}
}