瀏覽代碼

fix: skip library folders that are inaccessible or empty (#9291)

Claus Vium 1 年之前
父節點
當前提交
239727e896

+ 10 - 1
Emby.Server.Implementations/IO/ManagedFileSystem.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Globalization;
 using System.IO;
 using System.Linq;
+using System.Security;
 using Jellyfin.Extensions;
 using MediaBrowser.Common.Configuration;
 using MediaBrowser.Model.IO;
@@ -643,7 +644,15 @@ namespace Emby.Server.Implementations.IO
         /// <inheritdoc />
         public virtual IEnumerable<string> GetFileSystemEntryPaths(string path, bool recursive = false)
         {
-            return Directory.EnumerateFileSystemEntries(path, "*", GetEnumerationOptions(recursive));
+            try
+            {
+                return Directory.EnumerateFileSystemEntries(path, "*", GetEnumerationOptions(recursive));
+            }
+            catch (Exception ex) when (ex is UnauthorizedAccessException or DirectoryNotFoundException or SecurityException)
+            {
+                _logger.LogError(ex, "Failed to enumerate path {Path}", path);
+                return Enumerable.Empty<string>();
+            }
         }
 
         /// <inheritdoc />

+ 27 - 2
MediaBrowser.Controller/Entities/Folder.cs

@@ -331,8 +331,25 @@ namespace MediaBrowser.Controller.Entities
             }
         }
 
+        private static bool IsLibraryFolderAccessible(IDirectoryService directoryService, BaseItem item)
+        {
+            // For top parents i.e. Library folders, skip the validation if it's empty or inaccessible
+            if (item.IsTopParent && !directoryService.IsAccessible(item.ContainingFolderPath))
+            {
+                Logger.LogWarning("Library folder {LibraryFolderPath} is inaccessible or empty, skipping", item.ContainingFolderPath);
+                return false;
+            }
+
+            return true;
+        }
+
         private async Task ValidateChildrenInternal2(IProgress<double> progress, bool recursive, bool refreshChildMetadata, MetadataRefreshOptions refreshOptions, IDirectoryService directoryService, CancellationToken cancellationToken)
         {
+            if (!IsLibraryFolderAccessible(directoryService, this))
+            {
+                return;
+            }
+
             cancellationToken.ThrowIfCancellationRequested();
 
             var validChildren = new List<BaseItem>();
@@ -369,6 +386,11 @@ namespace MediaBrowser.Controller.Entities
 
                 foreach (var child in nonCachedChildren)
                 {
+                    if (!IsLibraryFolderAccessible(directoryService, child))
+                    {
+                        continue;
+                    }
+
                     if (currentChildren.TryGetValue(child.Id, out BaseItem currentChild))
                     {
                         validChildren.Add(currentChild);
@@ -392,8 +414,8 @@ namespace MediaBrowser.Controller.Entities
                     validChildren.Add(child);
                 }
 
-                // If any items were added or removed....
-                if (newItems.Count > 0 || currentChildren.Count != validChildren.Count)
+                // If it's an AggregateFolder, don't remove
+                if (!IsRoot && currentChildren.Count != validChildren.Count)
                 {
                     // That's all the new and changed ones - now see if there are any that are missing
                     var itemsRemoved = currentChildren.Values.Except(validChildren).ToList();
@@ -408,7 +430,10 @@ namespace MediaBrowser.Controller.Entities
                             LibraryManager.DeleteItem(item, new DeleteOptions { DeleteFileLocation = false }, this, false);
                         }
                     }
+                }
 
+                if (newItems.Count > 0)
+                {
                     LibraryManager.CreateItems(newItems, this, cancellationToken);
                 }
             }

+ 5 - 0
MediaBrowser.Controller/Providers/DirectoryService.cs

@@ -78,5 +78,10 @@ namespace MediaBrowser.Controller.Providers
 
             return filePaths;
         }
+
+        public bool IsAccessible(string path)
+        {
+            return _fileSystem.GetFileSystemEntryPaths(path).Any();
+        }
     }
 }

+ 2 - 0
MediaBrowser.Controller/Providers/IDirectoryService.cs

@@ -16,5 +16,7 @@ namespace MediaBrowser.Controller.Providers
         IReadOnlyList<string> GetFilePaths(string path);
 
         IReadOnlyList<string> GetFilePaths(string path, bool clearCache, bool sort = false);
+
+        bool IsAccessible(string path);
     }
 }