aboutsummaryrefslogtreecommitdiff
path: root/Emby.Server.Implementations/AppBase/BaseApplicationPaths.cs
blob: de722332a4a7bd16dd9e4653c2254812a0b238cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Jellyfin.Extensions;
using MediaBrowser.Common.Configuration;

namespace Emby.Server.Implementations.AppBase
{
    /// <summary>
    /// Provides a base class to hold common application paths used by both the UI and Server.
    /// This can be subclassed to add application-specific paths.
    /// </summary>
    public abstract class BaseApplicationPaths : IApplicationPaths
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="BaseApplicationPaths"/> class.
        /// </summary>
        /// <param name="programDataPath">The program data path.</param>
        /// <param name="logDirectoryPath">The log directory path.</param>
        /// <param name="configurationDirectoryPath">The configuration directory path.</param>
        /// <param name="cacheDirectoryPath">The cache directory path.</param>
        /// <param name="webDirectoryPath">The web directory path.</param>
        protected BaseApplicationPaths(
            string programDataPath,
            string logDirectoryPath,
            string configurationDirectoryPath,
            string cacheDirectoryPath,
            string webDirectoryPath)
        {
            ProgramDataPath = programDataPath;
            LogDirectoryPath = logDirectoryPath;
            ConfigurationDirectoryPath = configurationDirectoryPath;
            CachePath = cacheDirectoryPath;
            WebPath = webDirectoryPath;
            DataPath = Directory.CreateDirectory(Path.Combine(ProgramDataPath, "data")).FullName;
        }

        /// <inheritdoc/>
        public string ProgramDataPath { get; }

        /// <inheritdoc/>
        public string WebPath { get; }

        /// <inheritdoc/>
        public string ProgramSystemPath { get; } = AppContext.BaseDirectory;

        /// <inheritdoc/>
        public string DataPath { get; }

        /// <inheritdoc />
        public string VirtualDataPath => "%AppDataPath%";

        /// <inheritdoc/>
        public string ImageCachePath => Path.Combine(CachePath, "images");

        /// <inheritdoc/>
        public string PluginsPath => Path.Combine(ProgramDataPath, "plugins");

        /// <inheritdoc/>
        public string PluginConfigurationsPath => Path.Combine(PluginsPath, "configurations");

        /// <inheritdoc/>
        public string LogDirectoryPath { get; }

        /// <inheritdoc/>
        public string ConfigurationDirectoryPath { get; }

        /// <inheritdoc/>
        public string SystemConfigurationFilePath => Path.Combine(ConfigurationDirectoryPath, "system.xml");

        /// <inheritdoc/>
        public string CachePath { get; set; }

        /// <inheritdoc/>
        public string TempDirectory => Path.Join(Path.GetTempPath(), "jellyfin");

        /// <inheritdoc />
        public string TrickplayPath => Path.Combine(DataPath, "trickplay");

        /// <inheritdoc />
        public string BackupPath => Path.Combine(DataPath, "backups");

        /// <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)
        {
            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)
        {
            string? otherMarkers = null;
            try
            {
                otherMarkers = GetMarkers(path, recursive).FirstOrDefault(e => !Path.GetFileName(e.AsSpan()).Equals(markerName, StringComparison.OrdinalIgnoreCase));
            }
            catch
            {
                // Error while checking for marker files, assume none exist and keep going
                // TODO: add some logging
            }

            if (otherMarkers is not null)
            {
                throw new InvalidOperationException($"Expected to find only {markerName} but found marker for {otherMarkers}.");
            }

            var markerPath = Path.Combine(path, markerName);
            if (!File.Exists(markerPath))
            {
                FileHelper.CreateEmpty(markerPath);
            }
        }
    }
}