From c0cb454d4552c0d3ee94426c4ada489e7fc6aa4b Mon Sep 17 00:00:00 2001 From: Robert McRackan Date: Thu, 5 Sep 2024 09:07:47 -0400 Subject: [PATCH] Make recursive file enumerations safer --- Source/AppScaffolding/AppScaffolding.csproj | 2 +- Source/AppScaffolding/LibationScaffolding.cs | 15 +++++++++++---- Source/FileManager/BackgroundFileSystem.cs | 18 +++++++++++++++--- .../LibationFileManager/AudibleFileStorage.cs | 15 ++++++++++++--- 4 files changed, 39 insertions(+), 11 deletions(-) diff --git a/Source/AppScaffolding/AppScaffolding.csproj b/Source/AppScaffolding/AppScaffolding.csproj index d0e85dbb..1cf19bb0 100644 --- a/Source/AppScaffolding/AppScaffolding.csproj +++ b/Source/AppScaffolding/AppScaffolding.csproj @@ -2,7 +2,7 @@ net8.0 - 11.3.14.2 + 11.3.14.1 diff --git a/Source/AppScaffolding/LibationScaffolding.cs b/Source/AppScaffolding/LibationScaffolding.cs index 0d9c35bc..9cf704a6 100644 --- a/Source/AppScaffolding/LibationScaffolding.cs +++ b/Source/AppScaffolding/LibationScaffolding.cs @@ -9,9 +9,9 @@ using Dinah.Core; using Dinah.Core.IO; using Dinah.Core.Logging; using LibationFileManager; -using System.Runtime.InteropServices; using Newtonsoft.Json.Linq; using Serilog; +using System.Runtime.InteropServices; namespace AppScaffolding { @@ -230,7 +230,14 @@ namespace AppScaffolding // begin logging session with a form feed Log.Logger.Information("\r\n\f"); - Log.Logger.Information("Begin. {@DebugInfo}", new + + static int fileCount(FileManager.LongPath longPath) + { + try { return FileManager.FileUtility.SaferEnumerateFiles(longPath).Count(); } + catch { return -1; } + } + + Log.Logger.Information("Begin. {@DebugInfo}", new { AppName = EntryAssembly.GetName().Name, Version = BuildVersion.ToString(), @@ -255,10 +262,10 @@ namespace AppScaffolding config.InProgress, AudibleFileStorage.DownloadsInProgressDirectory, - DownloadsInProgressFiles = FileManager.FileUtility.SaferEnumerateFiles(AudibleFileStorage.DownloadsInProgressDirectory).Count(), + DownloadsInProgressFiles = fileCount(AudibleFileStorage.DownloadsInProgressDirectory), AudibleFileStorage.DecryptInProgressDirectory, - DecryptInProgressFiles = FileManager.FileUtility.SaferEnumerateFiles(AudibleFileStorage.DecryptInProgressDirectory).Count(), + DecryptInProgressFiles = fileCount(AudibleFileStorage.DecryptInProgressDirectory), disableIPv6 = AppContext.TryGetSwitch("System.Net.DisableIPv6", out bool disableIPv6Value), }); diff --git a/Source/FileManager/BackgroundFileSystem.cs b/Source/FileManager/BackgroundFileSystem.cs index 877f9160..e4ec7db2 100644 --- a/Source/FileManager/BackgroundFileSystem.cs +++ b/Source/FileManager/BackgroundFileSystem.cs @@ -50,7 +50,7 @@ namespace FileManager lock (fsCacheLocker) { fsCache.Clear(); - fsCache.AddRange(FileUtility.SaferEnumerateFiles(RootDirectory, SearchPattern, SearchOption)); + fsCache.AddRange(SafestEnumerateFiles(RootDirectory)); } } @@ -59,7 +59,7 @@ namespace FileManager Stop(); lock (fsCacheLocker) - fsCache.AddRange(FileUtility.SaferEnumerateFiles(RootDirectory, SearchPattern, SearchOption)); + fsCache.AddRange(SafestEnumerateFiles(RootDirectory)); directoryChangesEvents = new BlockingCollection(); fileSystemWatcher = new FileSystemWatcher(RootDirectory) @@ -152,11 +152,23 @@ namespace FileManager if (Path.GetFileName(path).Contains("LibationContext.db") || !File.Exists(path) && !Directory.Exists(path)) return; if (File.GetAttributes(path).HasFlag(FileAttributes.Directory)) - AddUniqueFiles(FileUtility.SaferEnumerateFiles(path, SearchPattern, SearchOption)); + AddUniqueFiles(SafestEnumerateFiles(path)); else AddUniqueFile(path); } + private IEnumerable SafestEnumerateFiles(string path) + { + try + { + return FileUtility.SaferEnumerateFiles(path, SearchPattern, SearchOption); + } + catch + { + return []; + } + } + private void AddUniqueFiles(IEnumerable newFiles) { foreach (var file in newFiles) diff --git a/Source/LibationFileManager/AudibleFileStorage.cs b/Source/LibationFileManager/AudibleFileStorage.cs index 4e91d850..0de15d83 100644 --- a/Source/LibationFileManager/AudibleFileStorage.cs +++ b/Source/LibationFileManager/AudibleFileStorage.cs @@ -25,9 +25,18 @@ namespace LibationFileManager static AudibleFileStorage() { //Clean up any partially-decrypted files from previous Libation instances. - //Do no clean DownloadsInProgressDirectory because those files are resumable - foreach (var tempFile in Directory.EnumerateFiles(DecryptInProgressDirectory)) - FileUtility.SaferDelete(tempFile); + //Do not clean DownloadsInProgressDirectory. Those files are resumable. + try + { + foreach (var tempFile in FileUtility.SaferEnumerateFiles(DecryptInProgressDirectory)) + FileUtility.SaferDelete(tempFile); + } + catch (Exception ex) + { + // since this is a static constructor which may be called very early, do not assume Serilog is initialized + try { Serilog.Log.Error(ex, "Error cleaning up partially-decrypted files"); } + catch { } + } }