From b88479b8b5bf90934a40cc52f2187e466fc30c3b Mon Sep 17 00:00:00 2001 From: Jonathan Jenne Date: Mon, 8 Jul 2019 12:18:58 +0200 Subject: [PATCH] ConfigManager: Test write access for config paths --- Filesystem/File.vb | 51 ++++++++++++++++++++++++++++ Filesystem/Filesystem.vbproj | 4 ++- Modules.Config/ConfigManager.vb | 59 ++++++++++++--------------------- 3 files changed, 75 insertions(+), 39 deletions(-) diff --git a/Filesystem/File.vb b/Filesystem/File.vb index e27264af..94a446a1 100644 --- a/Filesystem/File.vb +++ b/Filesystem/File.vb @@ -24,6 +24,8 @@ Public Class File Private ReadOnly _logger As Logger Private ReadOnly _logConfig As LogConfig + Private Const FILE_NAME_ACCESS_TEST = "accessTest.txt" + Public Sub New(LogConfig As LogConfig) _logConfig = LogConfig _logger = LogConfig.GetLogger() @@ -94,6 +96,55 @@ Public Class File IO.File.Move(FilePath, Path.Combine(Directory, oFileInfo.Name)) End Sub + ''' + ''' Tries to create a directory and returns its path. + ''' Returns a temp path if `DirectoryPath` can not be created or written to. + ''' + ''' The directory to create + ''' Should a write access test be performed? + ''' The used path + Public Function CreateDirectory(DirectoryPath As String, Optional TestWriteAccess As Boolean = True) As String + Dim oFinalPath As String + If Directory.Exists(DirectoryPath) Then + _logger.Debug("Directory {0} already exists. Skipping.", DirectoryPath) + oFinalPath = DirectoryPath + Else + Try + Directory.CreateDirectory(DirectoryPath) + oFinalPath = DirectoryPath + Catch ex As Exception + _logger.Error(ex) + _logger.Warn("Directory {0} could not be created. Temp path will be used instead.", DirectoryPath) + oFinalPath = Path.GetTempPath() + End Try + End If + + If TestWriteAccess AndAlso Not TestPathIsWritable(DirectoryPath) Then + _logger.Warn("Directory {0} is not writable. Temp path will be used instead.", DirectoryPath) + oFinalPath = Path.GetTempPath() + Else + oFinalPath = DirectoryPath + End If + + _logger.Debug("Using path {0}", oFinalPath) + + Return oFinalPath + End Function + + Public Function TestPathIsWritable(DirectoryPath As String) As Boolean + Try + Dim fileAccessPath = Path.Combine(DirectoryPath, FILE_NAME_ACCESS_TEST) + Using fs As FileStream = IO.File.Create(fileAccessPath) + fs.WriteByte(0) + End Using + + IO.File.Delete(fileAccessPath) + Return True + Catch ex As Exception + Return False + End Try + End Function + Public Function TestPathIsDirectory(Path As String) As Boolean If Not Directory.Exists(Path) Then Return False diff --git a/Filesystem/Filesystem.vbproj b/Filesystem/Filesystem.vbproj index eef47b43..56723e0a 100644 --- a/Filesystem/Filesystem.vbproj +++ b/Filesystem/Filesystem.vbproj @@ -79,7 +79,9 @@ - + + PreserveNewest + diff --git a/Modules.Config/ConfigManager.vb b/Modules.Config/ConfigManager.vb index 96daa001..b62830bc 100644 --- a/Modules.Config/ConfigManager.vb +++ b/Modules.Config/ConfigManager.vb @@ -11,8 +11,8 @@ Public Class ConfigManager(Of T) Private ReadOnly _LogConfig As LogConfig Private ReadOnly _Logger As Logger Private ReadOnly _File As Filesystem.File - Private ReadOnly _UserPath As String - Private ReadOnly _ComputerPath As String + Private ReadOnly _UserDirectory As String + Private ReadOnly _ComputerDirectory As String Private ReadOnly _TestMode As Boolean = False Private ReadOnly _Blueprint As T @@ -33,17 +33,17 @@ Public Class ConfigManager(Of T) ''' Public ReadOnly Property Config As T + ''' + ''' Path to the current user config. + ''' + ''' Public ReadOnly Property UserConfigPath As String - Get - Return _UserPath - End Get - End Property + ''' + ''' Path to the current computer config. Maybe the same as `UserConfigPath` + ''' + ''' Public ReadOnly Property ComputerConfigPath As String - Get - Return _ComputerPath - End Get - End Property ''' ''' Creates a new instance of the ConfigManager @@ -58,35 +58,18 @@ Public Class ConfigManager(Of T) _Logger = LogConfig.GetLogger() _File = New Filesystem.File(_LogConfig) - _UserPath = Path.Combine(UserConfigPath, USER_CONFIG_NAME) - _ComputerPath = Path.Combine(ComputerConfigPath, COMPUTER_CONFIG_NAME) - _ForceUserConfig = ForceUserConfig - _Blueprint = Activator.CreateInstance(Of T) _BlueprintType = _Blueprint.GetType _Serializer = New XmlSerializer(_BlueprintType) - If Not Directory.Exists(UserConfigPath) Then - _Logger.Debug("UserConfigPath {0} did not exist and was created", UserConfigPath) - Directory.CreateDirectory(UserConfigPath) - End If - - If Not _File.TestPathIsDirectory(UserConfigPath) Then - _Logger.Warn("UserConfigPath {0} is not a directory", UserConfigPath) - Throw New ArgumentException($"Path {UserConfigPath} is not a directory!") - End If - - If Not Directory.Exists(ComputerConfigPath) Then - _Logger.Debug("ComputerConfigPath {0} did not exist and was created", ComputerConfigPath) - Directory.CreateDirectory(ComputerConfigPath) - End If + _UserDirectory = _File.CreateDirectory(UserConfigPath) + _ComputerDirectory = _File.CreateDirectory(ComputerConfigPath) + _ForceUserConfig = ForceUserConfig - If Not _File.TestPathIsDirectory(ComputerConfigPath) Then - _Logger.Warn("ComputerConfigPath {0} is not a directory", ComputerConfigPath) - Throw New ArgumentException($"Path {ComputerConfigPath} is not a directory!") - End If + UserConfigPath = Path.Combine(_UserDirectory, USER_CONFIG_NAME) + ComputerConfigPath = Path.Combine(_ComputerDirectory, COMPUTER_CONFIG_NAME) - _Config = LoadConfig() + Config = LoadConfig() End Sub ''' @@ -105,7 +88,7 @@ Public Class ConfigManager(Of T) ''' True if save was successful, False otherwise Public Function Save(Optional ForceAll As Boolean = False) As Boolean Try - WriteToFile(_Config, _UserPath, ForceAll) + WriteToFile(Config, UserConfigPath, ForceAll) Return True Catch ex As Exception _Logger.Error(ex) @@ -169,9 +152,9 @@ Public Class ConfigManager(Of T) Private Function LoadComputerConfig(ByVal Config As T) As T - If File.Exists(_ComputerPath) Then + If File.Exists(ComputerConfigPath) Then Try - Dim oComputerConfig = ReadFromFile(_ComputerPath) + Dim oComputerConfig = ReadFromFile(ComputerConfigPath) CopyValues(oComputerConfig, Config) Catch ex As Exception _Logger.Error(ex) @@ -186,9 +169,9 @@ Public Class ConfigManager(Of T) End Function Private Function LoadUserConfig(ByVal Config As T) As T - If File.Exists(_UserPath) Then + If File.Exists(UserConfigPath) Then Try - Dim oUserConfig = ReadFromFile(_UserPath) + Dim oUserConfig = ReadFromFile(UserConfigPath) ' if user config exists If Not IsNothing(oUserConfig) Then