diff options
Diffstat (limited to 'Emby.Server.Implementations/IO')
| -rw-r--r-- | Emby.Server.Implementations/IO/FileRefresher.cs | 2 | ||||
| -rw-r--r-- | Emby.Server.Implementations/IO/LibraryMonitor.cs | 38 | ||||
| -rw-r--r-- | Emby.Server.Implementations/IO/ManagedFileSystem.cs | 120 | ||||
| -rw-r--r-- | Emby.Server.Implementations/IO/MbLinkShortcutHandler.cs | 2 | ||||
| -rw-r--r-- | Emby.Server.Implementations/IO/StreamHelper.cs | 2 |
5 files changed, 85 insertions, 79 deletions
diff --git a/Emby.Server.Implementations/IO/FileRefresher.cs b/Emby.Server.Implementations/IO/FileRefresher.cs index 7435e9d0b..47a83d77c 100644 --- a/Emby.Server.Implementations/IO/FileRefresher.cs +++ b/Emby.Server.Implementations/IO/FileRefresher.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; diff --git a/Emby.Server.Implementations/IO/LibraryMonitor.cs b/Emby.Server.Implementations/IO/LibraryMonitor.cs index 3353fae9d..e9d069cd3 100644 --- a/Emby.Server.Implementations/IO/LibraryMonitor.cs +++ b/Emby.Server.Implementations/IO/LibraryMonitor.cs @@ -1,3 +1,5 @@ +#nullable disable + #pragma warning disable CS1591 using System; @@ -40,6 +42,25 @@ namespace Emby.Server.Implementations.IO private bool _disposed = false; /// <summary> + /// Initializes a new instance of the <see cref="LibraryMonitor" /> class. + /// </summary> + /// <param name="logger">The logger.</param> + /// <param name="libraryManager">The library manager.</param> + /// <param name="configurationManager">The configuration manager.</param> + /// <param name="fileSystem">The filesystem.</param> + public LibraryMonitor( + ILogger<LibraryMonitor> logger, + ILibraryManager libraryManager, + IServerConfigurationManager configurationManager, + IFileSystem fileSystem) + { + _libraryManager = libraryManager; + _logger = logger; + _configurationManager = configurationManager; + _fileSystem = fileSystem; + } + + /// <summary> /// Add the path to our temporary ignore list. Use when writing to a path within our listening scope. /// </summary> /// <param name="path">The path.</param> @@ -93,21 +114,6 @@ namespace Emby.Server.Implementations.IO } } - /// <summary> - /// Initializes a new instance of the <see cref="LibraryMonitor" /> class. - /// </summary> - public LibraryMonitor( - ILogger<LibraryMonitor> logger, - ILibraryManager libraryManager, - IServerConfigurationManager configurationManager, - IFileSystem fileSystem) - { - _libraryManager = libraryManager; - _logger = logger; - _configurationManager = configurationManager; - _fileSystem = fileSystem; - } - private bool IsLibraryMonitorEnabled(BaseItem item) { if (item is BasePluginFolder) @@ -197,7 +203,7 @@ namespace Emby.Server.Implementations.IO /// <param name="lst">The LST.</param> /// <param name="path">The path.</param> /// <returns><c>true</c> if [contains parent folder] [the specified LST]; otherwise, <c>false</c>.</returns> - /// <exception cref="ArgumentNullException">path</exception> + /// <exception cref="ArgumentNullException"><paramref name="path"/> is <c>null</c>.</exception> private static bool ContainsParentFolder(IEnumerable<string> lst, string path) { if (string.IsNullOrEmpty(path)) diff --git a/Emby.Server.Implementations/IO/ManagedFileSystem.cs b/Emby.Server.Implementations/IO/ManagedFileSystem.cs index 3893a1577..eeee28842 100644 --- a/Emby.Server.Implementations/IO/ManagedFileSystem.cs +++ b/Emby.Server.Implementations/IO/ManagedFileSystem.cs @@ -2,16 +2,13 @@ using System; using System.Collections.Generic; -using System.Diagnostics; using System.Globalization; using System.IO; using System.Linq; -using System.Text; +using Jellyfin.Extensions; using MediaBrowser.Common.Configuration; using MediaBrowser.Model.IO; -using MediaBrowser.Model.System; using Microsoft.Extensions.Logging; -using OperatingSystem = MediaBrowser.Common.System.OperatingSystem; namespace Emby.Server.Implementations.IO { @@ -20,20 +17,18 @@ namespace Emby.Server.Implementations.IO /// </summary> public class ManagedFileSystem : IFileSystem { - protected ILogger<ManagedFileSystem> Logger; + private readonly ILogger<ManagedFileSystem> _logger; private readonly List<IShortcutHandler> _shortcutHandlers = new List<IShortcutHandler>(); private readonly string _tempPath; - private readonly bool _isEnvironmentCaseInsensitive; + private static readonly bool _isEnvironmentCaseInsensitive = OperatingSystem.IsWindows(); public ManagedFileSystem( ILogger<ManagedFileSystem> logger, IApplicationPaths applicationPaths) { - Logger = logger; + _logger = logger; _tempPath = applicationPaths.TempDirectory; - - _isEnvironmentCaseInsensitive = OperatingSystem.Id == OperatingSystemId.Windows; } public virtual void AddShortcutHandler(IShortcutHandler handler) @@ -46,7 +41,7 @@ namespace Emby.Server.Implementations.IO /// </summary> /// <param name="filename">The filename.</param> /// <returns><c>true</c> if the specified filename is shortcut; otherwise, <c>false</c>.</returns> - /// <exception cref="ArgumentNullException">filename</exception> + /// <exception cref="ArgumentNullException"><paramref name="filename"/> is <c>null</c>.</exception> public virtual bool IsShortcut(string filename) { if (string.IsNullOrEmpty(filename)) @@ -55,7 +50,7 @@ namespace Emby.Server.Implementations.IO } var extension = Path.GetExtension(filename); - return _shortcutHandlers.Any(i => string.Equals(extension, i.Extension, _isEnvironmentCaseInsensitive ? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal)); + return _shortcutHandlers.Any(i => string.Equals(extension, i.Extension, StringComparison.OrdinalIgnoreCase)); } /// <summary> @@ -63,8 +58,8 @@ namespace Emby.Server.Implementations.IO /// </summary> /// <param name="filename">The filename.</param> /// <returns>System.String.</returns> - /// <exception cref="ArgumentNullException">filename</exception> - public virtual string ResolveShortcut(string filename) + /// <exception cref="ArgumentNullException"><paramref name="filename"/> is <c>null</c>.</exception> + public virtual string? ResolveShortcut(string filename) { if (string.IsNullOrEmpty(filename)) { @@ -72,7 +67,7 @@ namespace Emby.Server.Implementations.IO } var extension = Path.GetExtension(filename); - var handler = _shortcutHandlers.FirstOrDefault(i => string.Equals(extension, i.Extension, StringComparison.OrdinalIgnoreCase)); + var handler = _shortcutHandlers.Find(i => string.Equals(extension, i.Extension, StringComparison.OrdinalIgnoreCase)); return handler?.Resolve(filename); } @@ -238,33 +233,31 @@ namespace Emby.Server.Implementations.IO result.IsDirectory = info is DirectoryInfo || (info.Attributes & FileAttributes.Directory) == FileAttributes.Directory; // if (!result.IsDirectory) - //{ + // { // result.IsHidden = (info.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden; - //} + // } if (info is FileInfo fileInfo) { result.Length = fileInfo.Length; - // Issue #2354 get the size of files behind symbolic links - if (fileInfo.Attributes.HasFlag(FileAttributes.ReparsePoint)) + // Issue #2354 get the size of files behind symbolic links. Also Enum.HasFlag is bad as it boxes! + if ((fileInfo.Attributes & FileAttributes.ReparsePoint) == FileAttributes.ReparsePoint) { try { - using (Stream thisFileStream = File.OpenRead(fileInfo.FullName)) + using (var fileHandle = File.OpenHandle(fileInfo.FullName, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { - result.Length = thisFileStream.Length; + result.Length = RandomAccess.GetLength(fileHandle); } } catch (FileNotFoundException ex) { // Dangling symlinks cannot be detected before opening the file unfortunately... - Logger.LogError(ex, "Reading the file size of the symlink at {Path} failed. Marking the file as not existing.", fileInfo.FullName); + _logger.LogError(ex, "Reading the file size of the symlink at {Path} failed. Marking the file as not existing.", fileInfo.FullName); result.Exists = false; } } - - result.DirectoryName = fileInfo.DirectoryName; } result.CreationTimeUtc = GetCreationTimeUtc(info); @@ -303,16 +296,37 @@ namespace Emby.Server.Implementations.IO /// <param name="filename">The filename.</param> /// <returns>System.String.</returns> /// <exception cref="ArgumentNullException">The filename is null.</exception> - public virtual string GetValidFilename(string filename) + public string GetValidFilename(string filename) { - var builder = new StringBuilder(filename); - - foreach (var c in Path.GetInvalidFileNameChars()) + var invalid = Path.GetInvalidFileNameChars(); + var first = filename.IndexOfAny(invalid); + if (first == -1) { - builder = builder.Replace(c, ' '); + // Fast path for clean strings + return filename; } - return builder.ToString(); + return string.Create( + filename.Length, + (filename, invalid, first), + (chars, state) => + { + state.filename.AsSpan().CopyTo(chars); + + chars[state.first++] = ' '; + + var len = chars.Length; + foreach (var c in state.invalid) + { + for (int i = state.first; i < len; i++) + { + if (chars[i] == c) + { + chars[i] = ' '; + } + } + } + }); } /// <summary> @@ -329,7 +343,7 @@ namespace Emby.Server.Implementations.IO } catch (Exception ex) { - Logger.LogError(ex, "Error determining CreationTimeUtc for {FullName}", info.FullName); + _logger.LogError(ex, "Error determining CreationTimeUtc for {FullName}", info.FullName); return DateTime.MinValue; } } @@ -368,7 +382,7 @@ namespace Emby.Server.Implementations.IO } catch (Exception ex) { - Logger.LogError(ex, "Error determining LastAccessTimeUtc for {FullName}", info.FullName); + _logger.LogError(ex, "Error determining LastAccessTimeUtc for {FullName}", info.FullName); return DateTime.MinValue; } } @@ -385,7 +399,7 @@ namespace Emby.Server.Implementations.IO public virtual void SetHidden(string path, bool isHidden) { - if (OperatingSystem.Id != OperatingSystemId.Windows) + if (!OperatingSystem.IsWindows()) { return; } @@ -407,9 +421,9 @@ namespace Emby.Server.Implementations.IO } } - public virtual void SetAttributes(string path, bool isHidden, bool isReadOnly) + public virtual void SetAttributes(string path, bool isHidden, bool readOnly) { - if (OperatingSystem.Id != OperatingSystemId.Windows) + if (!OperatingSystem.IsWindows()) { return; } @@ -421,14 +435,14 @@ namespace Emby.Server.Implementations.IO return; } - if (info.IsReadOnly == isReadOnly && info.IsHidden == isHidden) + if (info.IsReadOnly == readOnly && info.IsHidden == isHidden) { return; } var attributes = File.GetAttributes(path); - if (isReadOnly) + if (readOnly) { attributes = attributes | FileAttributes.ReadOnly; } @@ -585,7 +599,7 @@ namespace Emby.Server.Implementations.IO return GetFiles(path, null, false, recursive); } - public virtual IEnumerable<FileSystemMetadata> GetFiles(string path, IReadOnlyList<string> extensions, bool enableCaseSensitiveExtensions, bool recursive = false) + public virtual IEnumerable<FileSystemMetadata> GetFiles(string path, IReadOnlyList<string>? extensions, bool enableCaseSensitiveExtensions, bool recursive = false) { var enumerationOptions = GetEnumerationOptions(recursive); @@ -602,13 +616,13 @@ namespace Emby.Server.Implementations.IO { files = files.Where(i => { - var ext = i.Extension; - if (ext == null) + var ext = i.Extension.AsSpan(); + if (ext.IsEmpty) { return false; } - return extensions.Contains(ext, StringComparer.OrdinalIgnoreCase); + return extensions.Contains(ext, StringComparison.OrdinalIgnoreCase); }); } @@ -620,8 +634,7 @@ namespace Emby.Server.Implementations.IO var directoryInfo = new DirectoryInfo(path); var enumerationOptions = GetEnumerationOptions(recursive); - return ToMetadata(directoryInfo.EnumerateDirectories("*", enumerationOptions)) - .Concat(ToMetadata(directoryInfo.EnumerateFiles("*", enumerationOptions))); + return ToMetadata(directoryInfo.EnumerateFileSystemInfos("*", enumerationOptions)); } private IEnumerable<FileSystemMetadata> ToMetadata(IEnumerable<FileSystemInfo> infos) @@ -639,7 +652,7 @@ namespace Emby.Server.Implementations.IO return GetFilePaths(path, null, false, recursive); } - public virtual IEnumerable<string> GetFilePaths(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false) + public virtual IEnumerable<string> GetFilePaths(string path, string[]? extensions, bool enableCaseSensitiveExtensions, bool recursive = false) { var enumerationOptions = GetEnumerationOptions(recursive); @@ -656,13 +669,13 @@ namespace Emby.Server.Implementations.IO { files = files.Where(i => { - var ext = Path.GetExtension(i); - if (ext == null) + var ext = Path.GetExtension(i.AsSpan()); + if (ext.IsEmpty) { return false; } - return extensions.Contains(ext, StringComparer.OrdinalIgnoreCase); + return extensions.Contains(ext, StringComparison.OrdinalIgnoreCase); }); } @@ -684,20 +697,5 @@ namespace Emby.Server.Implementations.IO AttributesToSkip = 0 }; } - - private static void RunProcess(string path, string args, string workingDirectory) - { - using (var process = Process.Start(new ProcessStartInfo - { - Arguments = args, - FileName = path, - CreateNoWindow = true, - WorkingDirectory = workingDirectory, - WindowStyle = ProcessWindowStyle.Normal - })) - { - process.WaitForExit(); - } - } } } diff --git a/Emby.Server.Implementations/IO/MbLinkShortcutHandler.cs b/Emby.Server.Implementations/IO/MbLinkShortcutHandler.cs index e6696b8c4..76c58d5dc 100644 --- a/Emby.Server.Implementations/IO/MbLinkShortcutHandler.cs +++ b/Emby.Server.Implementations/IO/MbLinkShortcutHandler.cs @@ -17,7 +17,7 @@ namespace Emby.Server.Implementations.IO public string Extension => ".mblink"; - public string Resolve(string shortcutPath) + public string? Resolve(string shortcutPath) { if (string.IsNullOrEmpty(shortcutPath)) { diff --git a/Emby.Server.Implementations/IO/StreamHelper.cs b/Emby.Server.Implementations/IO/StreamHelper.cs index c16ebd61b..e4f5f4cf0 100644 --- a/Emby.Server.Implementations/IO/StreamHelper.cs +++ b/Emby.Server.Implementations/IO/StreamHelper.cs @@ -11,7 +11,7 @@ namespace Emby.Server.Implementations.IO { public class StreamHelper : IStreamHelper { - public async Task CopyToAsync(Stream source, Stream destination, int bufferSize, Action onStarted, CancellationToken cancellationToken) + public async Task CopyToAsync(Stream source, Stream destination, int bufferSize, Action? onStarted, CancellationToken cancellationToken) { byte[] buffer = ArrayPool<byte>.Shared.Rent(bufferSize); try |
