浏览代码

Check for path overlaps (#12832)

JPVenson 2 月之前
父节点
当前提交
8ee358de2c

+ 44 - 1
Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs

@@ -1,5 +1,7 @@
 using System;
+using System.Collections.Generic;
 using System.IO;
+using System.Linq;
 using MediaBrowser.Common.Configuration;
 
 namespace Emby.Server.Implementations.AppBase
@@ -30,7 +32,6 @@ namespace Emby.Server.Implementations.AppBase
             ConfigurationDirectoryPath = configurationDirectoryPath;
             CachePath = cacheDirectoryPath;
             WebPath = webDirectoryPath;
-
             DataPath = Directory.CreateDirectory(Path.Combine(ProgramDataPath, "data")).FullName;
         }
 
@@ -75,5 +76,47 @@ namespace Emby.Server.Implementations.AppBase
 
         /// <inheritdoc />
         public string TrickplayPath => Path.Combine(DataPath, "trickplay");
+
+        /// <inheritdoc />
+        public virtual void MakeSanityCheckOrThrow()
+        {
+            CreateAndCheckMarker(ConfigurationDirectoryPath, "config");
+            CreateAndCheckMarker(LogDirectoryPath, "log");
+            CreateAndCheckMarker(PluginsPath, "plugin");
+            CreateAndCheckMarker(ProgramDataPath, "data");
+            CreateAndCheckMarker(CachePath, "cache");
+            CreateAndCheckMarker(DataPath, "data");
+        }
+
+        /// <inheritdoc />
+        public void CreateAndCheckMarker(string path, string markerName, bool recursive = false)
+        {
+            if (!Directory.Exists(path))
+            {
+                Directory.CreateDirectory(path);
+            }
+
+            CheckOrCreateMarker(path, $".jellyfin-{markerName}", recursive);
+        }
+
+        private IEnumerable<string> GetMarkers(string path, bool recursive = false)
+        {
+            return Directory.EnumerateFiles(path, ".jellyfin-*", recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly);
+        }
+
+        private void CheckOrCreateMarker(string path, string markerName, bool recursive = false)
+        {
+            var otherMarkers = GetMarkers(path, recursive).FirstOrDefault(e => Path.GetFileName(e) != markerName);
+            if (otherMarkers != null)
+            {
+                throw new InvalidOperationException($"Exepected to find only {markerName} but found marker for {otherMarkers}.");
+            }
+
+            var markerPath = Path.Combine(path, markerName);
+            if (!File.Exists(markerPath))
+            {
+                File.Create(markerPath).Dispose();
+            }
+        }
     }
 }

+ 1 - 0
Emby.Server.Implementations/AppBase/BaseConfigurationManager.cs

@@ -227,6 +227,7 @@ namespace Emby.Server.Implementations.AppBase
 
             Logger.LogInformation("Setting cache path: {Path}", cachePath);
             ((BaseApplicationPaths)CommonApplicationPaths).CachePath = cachePath;
+            CommonApplicationPaths.CreateAndCheckMarker(((BaseApplicationPaths)CommonApplicationPaths).CachePath, "cache");
         }
 
         /// <summary>

+ 0 - 2
Emby.Server.Implementations/Library/LibraryManager.cs

@@ -768,8 +768,6 @@ namespace Emby.Server.Implementations.Library
         {
             var rootFolderPath = _configurationManager.ApplicationPaths.RootFolderPath;
 
-            Directory.CreateDirectory(rootFolderPath);
-
             var rootFolder = GetItemById(GetNewItemId(rootFolderPath, typeof(AggregateFolder))) as AggregateFolder ??
                              (ResolvePath(_fileSystem.GetDirectoryInfo(rootFolderPath)) as Folder ?? throw new InvalidOperationException("Something went very wong"))
                              .DeepCopy<Folder, AggregateFolder>();

+ 7 - 0
Emby.Server.Implementations/ServerApplicationPaths.cs

@@ -96,5 +96,12 @@ namespace Emby.Server.Implementations
 
         /// <inheritdoc />
         public string VirtualInternalMetadataPath => "%MetadataPath%";
+
+        /// <inheritdoc/>
+        public override void MakeSanityCheckOrThrow()
+        {
+            base.MakeSanityCheckOrThrow();
+            CreateAndCheckMarker(RootFolderPath, "root");
+        }
     }
 }

+ 1 - 0
Jellyfin.Server/Program.cs

@@ -77,6 +77,7 @@ namespace Jellyfin.Server
         {
             _startTimestamp = Stopwatch.GetTimestamp();
             ServerApplicationPaths appPaths = StartupHelpers.CreateApplicationPaths(options);
+            appPaths.MakeSanityCheckOrThrow();
 
             // $JELLYFIN_LOG_DIR needs to be set for the logger configuration manager
             Environment.SetEnvironmentVariable("JELLYFIN_LOG_DIR", appPaths.LogDirectoryPath);

+ 1 - 2
MediaBrowser.Common/Configuration/EncodingConfigurationExtensions.cs

@@ -35,8 +35,7 @@ namespace MediaBrowser.Common.Configuration
                 transcodingTempPath = Path.Combine(configurationManager.CommonApplicationPaths.CachePath, "transcodes");
             }
 
-            // Make sure the directory exists
-            Directory.CreateDirectory(transcodingTempPath);
+            configurationManager.CommonApplicationPaths.CreateAndCheckMarker(transcodingTempPath, "transcode", true);
             return transcodingTempPath;
         }
     }

+ 13 - 0
MediaBrowser.Common/Configuration/IApplicationPaths.cs

@@ -90,5 +90,18 @@ namespace MediaBrowser.Common.Configuration
         /// </summary>
         /// <value>The trickplay path.</value>
         string TrickplayPath { get; }
+
+        /// <summary>
+        /// Checks and creates all known base paths.
+        /// </summary>
+        void MakeSanityCheckOrThrow();
+
+        /// <summary>
+        /// Checks and creates the given path and adds it with a marker file if non existant.
+        /// </summary>
+        /// <param name="path">The path to check.</param>
+        /// <param name="markerName">The common marker file name.</param>
+        /// <param name="recursive">Check for other settings paths recursivly.</param>
+        void CreateAndCheckMarker(string path, string markerName, bool recursive = false);
     }
 }

+ 4 - 0
MediaBrowser.Controller/IServerApplicationPaths.cs

@@ -2,6 +2,10 @@
 
 #pragma warning disable CS1591
 
+using System;
+using System.Collections.Generic;
+using System.IO;
+using System.Linq;
 using MediaBrowser.Common.Configuration;
 
 namespace MediaBrowser.Controller