| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179 | 
							- using System;
 
- using System.Collections.Generic;
 
- using System.Diagnostics;
 
- using System.IO;
 
- using System.Linq;
 
- using System.Text;
 
- using MediaBrowser.Model.IO;
 
- using Microsoft.Extensions.Logging;
 
- using MediaBrowser.Model.System;
 
- namespace Emby.Server.Implementations.IO
 
- {
 
-     /// <summary>
 
-     /// Class ManagedFileSystem
 
-     /// </summary>
 
-     public class ManagedFileSystem : IFileSystem
 
-     {
 
-         protected ILogger Logger;
 
-         private readonly bool _supportsAsyncFileStreams;
 
-         private char[] _invalidFileNameChars;
 
-         private readonly List<IShortcutHandler> _shortcutHandlers = new List<IShortcutHandler>();
 
-         private bool EnableSeparateFileAndDirectoryQueries;
 
-         private string _tempPath;
 
-         private SharpCifsFileSystem _sharpCifsFileSystem;
 
-         private IEnvironmentInfo _environmentInfo;
 
-         private bool _isEnvironmentCaseInsensitive;
 
-         private string _defaultDirectory;
 
-         public ManagedFileSystem(ILogger logger, IEnvironmentInfo environmentInfo, string defaultDirectory, string tempPath, bool enableSeparateFileAndDirectoryQueries)
 
-         {
 
-             Logger = logger;
 
-             _supportsAsyncFileStreams = true;
 
-             _tempPath = tempPath;
 
-             _environmentInfo = environmentInfo;
 
-             _defaultDirectory = defaultDirectory;
 
-             // On Linux with mono, this needs to be true or symbolic links are ignored
 
-             EnableSeparateFileAndDirectoryQueries = enableSeparateFileAndDirectoryQueries;
 
-             SetInvalidFileNameChars(environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows);
 
-             _sharpCifsFileSystem = new SharpCifsFileSystem(environmentInfo.OperatingSystem);
 
-             _isEnvironmentCaseInsensitive = environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.Windows;
 
-         }
 
-         public string DefaultDirectory
 
-         {
 
-             get
 
-             {
 
-                 var value = _defaultDirectory;
 
-                 if (!string.IsNullOrEmpty(value))
 
-                 {
 
-                     try
 
-                     {
 
-                         if (DirectoryExists(value))
 
-                         {
 
-                             return value;
 
-                         }
 
-                     }
 
-                     catch
 
-                     {
 
-                     }
 
-                 }
 
-                 return null;
 
-             }
 
-         }
 
-         public void AddShortcutHandler(IShortcutHandler handler)
 
-         {
 
-             _shortcutHandlers.Add(handler);
 
-         }
 
-         protected void SetInvalidFileNameChars(bool enableManagedInvalidFileNameChars)
 
-         {
 
-             if (enableManagedInvalidFileNameChars)
 
-             {
 
-                 _invalidFileNameChars = Path.GetInvalidFileNameChars();
 
-             }
 
-             else
 
-             {
 
-                 // Be consistent across platforms because the windows server will fail to query network shares that don't follow windows conventions
 
-                 // https://referencesource.microsoft.com/#mscorlib/system/io/path.cs
 
-                 _invalidFileNameChars = new char[] { '\"', '<', '>', '|', '\0', (Char)1, (Char)2, (Char)3, (Char)4, (Char)5, (Char)6, (Char)7, (Char)8, (Char)9, (Char)10, (Char)11, (Char)12, (Char)13, (Char)14, (Char)15, (Char)16, (Char)17, (Char)18, (Char)19, (Char)20, (Char)21, (Char)22, (Char)23, (Char)24, (Char)25, (Char)26, (Char)27, (Char)28, (Char)29, (Char)30, (Char)31, ':', '*', '?', '\\', '/' };
 
-             }
 
-         }
 
-         public char DirectorySeparatorChar
 
-         {
 
-             get
 
-             {
 
-                 return Path.DirectorySeparatorChar;
 
-             }
 
-         }
 
-         public string GetFullPath(string path)
 
-         {
 
-             return Path.GetFullPath(path);
 
-         }
 
-         /// <summary>
 
-         /// Determines whether the specified filename is shortcut.
 
-         /// </summary>
 
-         /// <param name="filename">The filename.</param>
 
-         /// <returns><c>true</c> if the specified filename is shortcut; otherwise, <c>false</c>.</returns>
 
-         /// <exception cref="System.ArgumentNullException">filename</exception>
 
-         public virtual bool IsShortcut(string filename)
 
-         {
 
-             if (string.IsNullOrEmpty(filename))
 
-             {
 
-                 throw new ArgumentNullException("filename");
 
-             }
 
-             var extension = Path.GetExtension(filename);
 
-             return _shortcutHandlers.Any(i => string.Equals(extension, i.Extension, StringComparison.OrdinalIgnoreCase));
 
-         }
 
-         /// <summary>
 
-         /// Resolves the shortcut.
 
-         /// </summary>
 
-         /// <param name="filename">The filename.</param>
 
-         /// <returns>System.String.</returns>
 
-         /// <exception cref="System.ArgumentNullException">filename</exception>
 
-         public virtual string ResolveShortcut(string filename)
 
-         {
 
-             if (string.IsNullOrEmpty(filename))
 
-             {
 
-                 throw new ArgumentNullException("filename");
 
-             }
 
-             var extension = Path.GetExtension(filename);
 
-             var handler = _shortcutHandlers.FirstOrDefault(i => string.Equals(extension, i.Extension, StringComparison.OrdinalIgnoreCase));
 
-             if (handler != null)
 
-             {
 
-                 return handler.Resolve(filename);
 
-             }
 
-             return null;
 
-         }
 
-         public string MakeAbsolutePath(string folderPath, string filePath)
 
-         {
 
-             if (String.IsNullOrWhiteSpace(filePath)) return filePath;
 
-             if (filePath.Contains(@"://")) return filePath; //stream
 
-             if (filePath.Length > 3 && filePath[1] == ':' && filePath[2] == '/') return filePath; //absolute local path
 
-             // unc path
 
-             if (filePath.StartsWith("\\\\"))
 
-             {
 
-                 return filePath;
 
-             }
 
-             var firstChar = filePath[0];
 
-             if (firstChar == '/')
 
-             {
 
-                 // For this we don't really know. 
 
-                 return filePath;
 
-             }
 
-             if (firstChar == '\\') //relative path
 
-             {
 
-                 filePath = filePath.Substring(1);
 
-             }
 
-             try
 
-             {
 
-                 string path = System.IO.Path.Combine(folderPath, filePath);
 
-                 path = System.IO.Path.GetFullPath(path);
 
-                 return path;
 
-             }
 
-             catch (ArgumentException)
 
-             {
 
-                 return filePath;
 
-             }
 
-             catch (PathTooLongException)
 
-             {
 
-                 return filePath;
 
-             }
 
-             catch (NotSupportedException)
 
-             {
 
-                 return filePath;
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// Creates the shortcut.
 
-         /// </summary>
 
-         /// <param name="shortcutPath">The shortcut path.</param>
 
-         /// <param name="target">The target.</param>
 
-         /// <exception cref="System.ArgumentNullException">
 
-         /// shortcutPath
 
-         /// or
 
-         /// target
 
-         /// </exception>
 
-         public void CreateShortcut(string shortcutPath, string target)
 
-         {
 
-             if (string.IsNullOrEmpty(shortcutPath))
 
-             {
 
-                 throw new ArgumentNullException("shortcutPath");
 
-             }
 
-             if (string.IsNullOrEmpty(target))
 
-             {
 
-                 throw new ArgumentNullException("target");
 
-             }
 
-             var extension = Path.GetExtension(shortcutPath);
 
-             var handler = _shortcutHandlers.FirstOrDefault(i => string.Equals(extension, i.Extension, StringComparison.OrdinalIgnoreCase));
 
-             if (handler != null)
 
-             {
 
-                 handler.Create(shortcutPath, target);
 
-             }
 
-             else
 
-             {
 
-                 throw new NotImplementedException();
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// Returns a <see cref="FileSystemMetadata"/> object for the specified file or directory path.
 
-         /// </summary>
 
-         /// <param name="path">A path to a file or directory.</param>
 
-         /// <returns>A <see cref="FileSystemMetadata"/> object.</returns>
 
-         /// <remarks>If the specified path points to a directory, the returned <see cref="FileSystemMetadata"/> object's
 
-         /// <see cref="FileSystemMetadata.IsDirectory"/> property will be set to true and all other properties will reflect the properties of the directory.</remarks>
 
-         public FileSystemMetadata GetFileSystemInfo(string path)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.GetFileSystemInfo(path);
 
-             }
 
-             // Take a guess to try and avoid two file system hits, but we'll double-check by calling Exists
 
-             if (Path.HasExtension(path))
 
-             {
 
-                 var fileInfo = new FileInfo(path);
 
-                 if (fileInfo.Exists)
 
-                 {
 
-                     return GetFileSystemMetadata(fileInfo);
 
-                 }
 
-                 return GetFileSystemMetadata(new DirectoryInfo(path));
 
-             }
 
-             else
 
-             {
 
-                 var fileInfo = new DirectoryInfo(path);
 
-                 if (fileInfo.Exists)
 
-                 {
 
-                     return GetFileSystemMetadata(fileInfo);
 
-                 }
 
-                 return GetFileSystemMetadata(new FileInfo(path));
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// Returns a <see cref="FileSystemMetadata"/> object for the specified file path.
 
-         /// </summary>
 
-         /// <param name="path">A path to a file.</param>
 
-         /// <returns>A <see cref="FileSystemMetadata"/> object.</returns>
 
-         /// <remarks><para>If the specified path points to a directory, the returned <see cref="FileSystemMetadata"/> object's
 
-         /// <see cref="FileSystemMetadata.IsDirectory"/> property and the <see cref="FileSystemMetadata.Exists"/> property will both be set to false.</para>
 
-         /// <para>For automatic handling of files <b>and</b> directories, use <see cref="GetFileSystemInfo"/>.</para></remarks>
 
-         public FileSystemMetadata GetFileInfo(string path)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.GetFileInfo(path);
 
-             }
 
-             var fileInfo = new FileInfo(path);
 
-             return GetFileSystemMetadata(fileInfo);
 
-         }
 
-         /// <summary>
 
-         /// Returns a <see cref="FileSystemMetadata"/> object for the specified directory path.
 
-         /// </summary>
 
-         /// <param name="path">A path to a directory.</param>
 
-         /// <returns>A <see cref="FileSystemMetadata"/> object.</returns>
 
-         /// <remarks><para>If the specified path points to a file, the returned <see cref="FileSystemMetadata"/> object's
 
-         /// <see cref="FileSystemMetadata.IsDirectory"/> property will be set to true and the <see cref="FileSystemMetadata.Exists"/> property will be set to false.</para>
 
-         /// <para>For automatic handling of files <b>and</b> directories, use <see cref="GetFileSystemInfo"/>.</para></remarks>
 
-         public FileSystemMetadata GetDirectoryInfo(string path)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.GetDirectoryInfo(path);
 
-             }
 
-             var fileInfo = new DirectoryInfo(path);
 
-             return GetFileSystemMetadata(fileInfo);
 
-         }
 
-         private FileSystemMetadata GetFileSystemMetadata(FileSystemInfo info)
 
-         {
 
-             var result = new FileSystemMetadata();
 
-             result.Exists = info.Exists;
 
-             result.FullName = info.FullName;
 
-             result.Extension = info.Extension;
 
-             result.Name = info.Name;
 
-             if (result.Exists)
 
-             {
 
-                 result.IsDirectory = info is DirectoryInfo || (info.Attributes & FileAttributes.Directory) == FileAttributes.Directory;
 
-                 //if (!result.IsDirectory)
 
-                 //{
 
-                 //    result.IsHidden = (info.Attributes & FileAttributes.Hidden) == FileAttributes.Hidden;
 
-                 //}
 
-                 var fileInfo = info as FileInfo;
 
-                 if (fileInfo != null)
 
-                 {
 
-                     result.Length = fileInfo.Length;
 
-                     result.DirectoryName = fileInfo.DirectoryName;
 
-                 }
 
-                 result.CreationTimeUtc = GetCreationTimeUtc(info);
 
-                 result.LastWriteTimeUtc = GetLastWriteTimeUtc(info);
 
-             }
 
-             else
 
-             {
 
-                 result.IsDirectory = info is DirectoryInfo;
 
-             }
 
-             return result;
 
-         }
 
-         private ExtendedFileSystemInfo GetExtendedFileSystemInfo(string path)
 
-         {
 
-             var result = new ExtendedFileSystemInfo();
 
-             var info = new FileInfo(path);
 
-             if (info.Exists)
 
-             {
 
-                 result.Exists = true;
 
-                 var attributes = info.Attributes;
 
-                 result.IsHidden = (attributes & FileAttributes.Hidden) == FileAttributes.Hidden;
 
-                 result.IsReadOnly = (attributes & FileAttributes.ReadOnly) == FileAttributes.ReadOnly;
 
-             }
 
-             return result;
 
-         }
 
-         /// <summary>
 
-         /// The space char
 
-         /// </summary>
 
-         private const char SpaceChar = ' ';
 
-         /// <summary>
 
-         /// Takes a filename and removes invalid characters
 
-         /// </summary>
 
-         /// <param name="filename">The filename.</param>
 
-         /// <returns>System.String.</returns>
 
-         /// <exception cref="System.ArgumentNullException">filename</exception>
 
-         public string GetValidFilename(string filename)
 
-         {
 
-             var builder = new StringBuilder(filename);
 
-             foreach (var c in _invalidFileNameChars)
 
-             {
 
-                 builder = builder.Replace(c, SpaceChar);
 
-             }
 
-             return builder.ToString();
 
-         }
 
-         /// <summary>
 
-         /// Gets the creation time UTC.
 
-         /// </summary>
 
-         /// <param name="info">The info.</param>
 
-         /// <returns>DateTime.</returns>
 
-         public DateTime GetCreationTimeUtc(FileSystemInfo info)
 
-         {
 
-             // This could throw an error on some file systems that have dates out of range
 
-             try
 
-             {
 
-                 return info.CreationTimeUtc;
 
-             }
 
-             catch (Exception ex)
 
-             {
 
-                 Logger.LogError(ex, "Error determining CreationTimeUtc for {FullName}", info.FullName);
 
-                 return DateTime.MinValue;
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// Gets the creation time UTC.
 
-         /// </summary>
 
-         /// <param name="path">The path.</param>
 
-         /// <returns>DateTime.</returns>
 
-         public DateTime GetCreationTimeUtc(string path)
 
-         {
 
-             return GetCreationTimeUtc(GetFileSystemInfo(path));
 
-         }
 
-         public DateTime GetCreationTimeUtc(FileSystemMetadata info)
 
-         {
 
-             return info.CreationTimeUtc;
 
-         }
 
-         public DateTime GetLastWriteTimeUtc(FileSystemMetadata info)
 
-         {
 
-             return info.LastWriteTimeUtc;
 
-         }
 
-         /// <summary>
 
-         /// Gets the creation time UTC.
 
-         /// </summary>
 
-         /// <param name="info">The info.</param>
 
-         /// <returns>DateTime.</returns>
 
-         public DateTime GetLastWriteTimeUtc(FileSystemInfo info)
 
-         {
 
-             // This could throw an error on some file systems that have dates out of range
 
-             try
 
-             {
 
-                 return info.LastWriteTimeUtc;
 
-             }
 
-             catch (Exception ex)
 
-             {
 
-                 Logger.LogError(ex, "Error determining LastAccessTimeUtc for {FullName}", info.FullName);
 
-                 return DateTime.MinValue;
 
-             }
 
-         }
 
-         /// <summary>
 
-         /// Gets the last write time UTC.
 
-         /// </summary>
 
-         /// <param name="path">The path.</param>
 
-         /// <returns>DateTime.</returns>
 
-         public DateTime GetLastWriteTimeUtc(string path)
 
-         {
 
-             return GetLastWriteTimeUtc(GetFileSystemInfo(path));
 
-         }
 
-         /// <summary>
 
-         /// Gets the file stream.
 
-         /// </summary>
 
-         /// <param name="path">The path.</param>
 
-         /// <param name="mode">The mode.</param>
 
-         /// <param name="access">The access.</param>
 
-         /// <param name="share">The share.</param>
 
-         /// <param name="isAsync">if set to <c>true</c> [is asynchronous].</param>
 
-         /// <returns>FileStream.</returns>
 
-         public Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, bool isAsync = false)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.GetFileStream(path, mode, access, share);
 
-             }
 
-             if (_supportsAsyncFileStreams && isAsync)
 
-             {
 
-                 return GetFileStream(path, mode, access, share, FileOpenOptions.Asynchronous);
 
-             }
 
-             return GetFileStream(path, mode, access, share, FileOpenOptions.None);
 
-         }
 
-         public Stream GetFileStream(string path, FileOpenMode mode, FileAccessMode access, FileShareMode share, FileOpenOptions fileOpenOptions)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.GetFileStream(path, mode, access, share);
 
-             }
 
-             var defaultBufferSize = 4096;
 
-             return new FileStream(path, GetFileMode(mode), GetFileAccess(access), GetFileShare(share), defaultBufferSize, GetFileOptions(fileOpenOptions));
 
-         }
 
-         private FileOptions GetFileOptions(FileOpenOptions mode)
 
-         {
 
-             var val = (int)mode;
 
-             return (FileOptions)val;
 
-         }
 
-         private FileMode GetFileMode(FileOpenMode mode)
 
-         {
 
-             switch (mode)
 
-             {
 
-                 //case FileOpenMode.Append:
 
-                 //    return FileMode.Append;
 
-                 case FileOpenMode.Create:
 
-                     return FileMode.Create;
 
-                 case FileOpenMode.CreateNew:
 
-                     return FileMode.CreateNew;
 
-                 case FileOpenMode.Open:
 
-                     return FileMode.Open;
 
-                 case FileOpenMode.OpenOrCreate:
 
-                     return FileMode.OpenOrCreate;
 
-                 //case FileOpenMode.Truncate:
 
-                 //    return FileMode.Truncate;
 
-                 default:
 
-                     throw new Exception("Unrecognized FileOpenMode");
 
-             }
 
-         }
 
-         private FileAccess GetFileAccess(FileAccessMode mode)
 
-         {
 
-             switch (mode)
 
-             {
 
-                 //case FileAccessMode.ReadWrite:
 
-                 //    return FileAccess.ReadWrite;
 
-                 case FileAccessMode.Write:
 
-                     return FileAccess.Write;
 
-                 case FileAccessMode.Read:
 
-                     return FileAccess.Read;
 
-                 default:
 
-                     throw new Exception("Unrecognized FileAccessMode");
 
-             }
 
-         }
 
-         private FileShare GetFileShare(FileShareMode mode)
 
-         {
 
-             switch (mode)
 
-             {
 
-                 case FileShareMode.ReadWrite:
 
-                     return FileShare.ReadWrite;
 
-                 case FileShareMode.Write:
 
-                     return FileShare.Write;
 
-                 case FileShareMode.Read:
 
-                     return FileShare.Read;
 
-                 case FileShareMode.None:
 
-                     return FileShare.None;
 
-                 default:
 
-                     throw new Exception("Unrecognized FileShareMode");
 
-             }
 
-         }
 
-         public void SetHidden(string path, bool isHidden)
 
-         {
 
-             if (_environmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows)
 
-             {
 
-                 return;
 
-             }
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 _sharpCifsFileSystem.SetHidden(path, isHidden);
 
-                 return;
 
-             }
 
-             var info = GetExtendedFileSystemInfo(path);
 
-             if (info.Exists && info.IsHidden != isHidden)
 
-             {
 
-                 if (isHidden)
 
-                 {
 
-                     File.SetAttributes(path, File.GetAttributes(path) | FileAttributes.Hidden);
 
-                 }
 
-                 else
 
-                 {
 
-                     FileAttributes attributes = File.GetAttributes(path);
 
-                     attributes = RemoveAttribute(attributes, FileAttributes.Hidden);
 
-                     File.SetAttributes(path, attributes);
 
-                 }
 
-             }
 
-         }
 
-         public void SetReadOnly(string path, bool isReadOnly)
 
-         {
 
-             if (_environmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows)
 
-             {
 
-                 return;
 
-             }
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 _sharpCifsFileSystem.SetReadOnly(path, isReadOnly);
 
-                 return;
 
-             }
 
-             var info = GetExtendedFileSystemInfo(path);
 
-             if (info.Exists && info.IsReadOnly != isReadOnly)
 
-             {
 
-                 if (isReadOnly)
 
-                 {
 
-                     File.SetAttributes(path, File.GetAttributes(path) | FileAttributes.ReadOnly);
 
-                 }
 
-                 else
 
-                 {
 
-                     FileAttributes attributes = File.GetAttributes(path);
 
-                     attributes = RemoveAttribute(attributes, FileAttributes.ReadOnly);
 
-                     File.SetAttributes(path, attributes);
 
-                 }
 
-             }
 
-         }
 
-         public void SetAttributes(string path, bool isHidden, bool isReadOnly)
 
-         {
 
-             if (_environmentInfo.OperatingSystem != MediaBrowser.Model.System.OperatingSystem.Windows)
 
-             {
 
-                 return;
 
-             }
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 _sharpCifsFileSystem.SetAttributes(path, isHidden, isReadOnly);
 
-                 return;
 
-             }
 
-             var info = GetExtendedFileSystemInfo(path);
 
-             if (!info.Exists)
 
-             {
 
-                 return;
 
-             }
 
-             if (info.IsReadOnly == isReadOnly && info.IsHidden == isHidden)
 
-             {
 
-                 return;
 
-             }
 
-             var attributes = File.GetAttributes(path);
 
-             if (isReadOnly)
 
-             {
 
-                 attributes = attributes | FileAttributes.ReadOnly;
 
-             }
 
-             else
 
-             {
 
-                 attributes = RemoveAttribute(attributes, FileAttributes.ReadOnly);
 
-             }
 
-             if (isHidden)
 
-             {
 
-                 attributes = attributes | FileAttributes.Hidden;
 
-             }
 
-             else
 
-             {
 
-                 attributes = RemoveAttribute(attributes, FileAttributes.Hidden);
 
-             }
 
-             File.SetAttributes(path, attributes);
 
-         }
 
-         private static FileAttributes RemoveAttribute(FileAttributes attributes, FileAttributes attributesToRemove)
 
-         {
 
-             return attributes & ~attributesToRemove;
 
-         }
 
-         /// <summary>
 
-         /// Swaps the files.
 
-         /// </summary>
 
-         /// <param name="file1">The file1.</param>
 
-         /// <param name="file2">The file2.</param>
 
-         public void SwapFiles(string file1, string file2)
 
-         {
 
-             if (string.IsNullOrEmpty(file1))
 
-             {
 
-                 throw new ArgumentNullException("file1");
 
-             }
 
-             if (string.IsNullOrEmpty(file2))
 
-             {
 
-                 throw new ArgumentNullException("file2");
 
-             }
 
-             var temp1 = Path.Combine(_tempPath, Guid.NewGuid().ToString("N"));
 
-             // Copying over will fail against hidden files
 
-             SetHidden(file1, false);
 
-             SetHidden(file2, false);
 
-             Directory.CreateDirectory(_tempPath);
 
-             CopyFile(file1, temp1, true);
 
-             CopyFile(file2, file1, true);
 
-             CopyFile(temp1, file2, true);
 
-         }
 
-         private char GetDirectorySeparatorChar(string path)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.GetDirectorySeparatorChar(path);
 
-             }
 
-             return Path.DirectorySeparatorChar;
 
-         }
 
-         public bool ContainsSubPath(string parentPath, string path)
 
-         {
 
-             if (string.IsNullOrEmpty(parentPath))
 
-             {
 
-                 throw new ArgumentNullException("parentPath");
 
-             }
 
-             if (string.IsNullOrEmpty(path))
 
-             {
 
-                 throw new ArgumentNullException("path");
 
-             }
 
-             var separatorChar = GetDirectorySeparatorChar(parentPath);
 
-             return path.IndexOf(parentPath.TrimEnd(separatorChar) + separatorChar, StringComparison.OrdinalIgnoreCase) != -1;
 
-         }
 
-         public bool IsRootPath(string path)
 
-         {
 
-             if (string.IsNullOrEmpty(path))
 
-             {
 
-                 throw new ArgumentNullException("path");
 
-             }
 
-             var parent = GetDirectoryName(path);
 
-             if (!string.IsNullOrEmpty(parent))
 
-             {
 
-                 return false;
 
-             }
 
-             return true;
 
-         }
 
-         public string GetDirectoryName(string path)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.GetDirectoryName(path);
 
-             }
 
-             return Path.GetDirectoryName(path);
 
-         }
 
-         public string NormalizePath(string path)
 
-         {
 
-             if (string.IsNullOrEmpty(path))
 
-             {
 
-                 throw new ArgumentNullException("path");
 
-             }
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.NormalizePath(path);
 
-             }
 
-             if (path.EndsWith(":\\", StringComparison.OrdinalIgnoreCase))
 
-             {
 
-                 return path;
 
-             }
 
-             return path.TrimEnd(GetDirectorySeparatorChar(path));
 
-         }
 
-         public bool AreEqual(string path1, string path2)
 
-         {
 
-             if (path1 == null && path2 == null)
 
-             {
 
-                 return true;
 
-             }
 
-             if (path1 == null || path2 == null)
 
-             {
 
-                 return false;
 
-             }
 
-             return string.Equals(NormalizePath(path1), NormalizePath(path2), StringComparison.OrdinalIgnoreCase);
 
-         }
 
-         public string GetFileNameWithoutExtension(FileSystemMetadata info)
 
-         {
 
-             if (info.IsDirectory)
 
-             {
 
-                 return info.Name;
 
-             }
 
-             return Path.GetFileNameWithoutExtension(info.FullName);
 
-         }
 
-         public string GetFileNameWithoutExtension(string path)
 
-         {
 
-             return Path.GetFileNameWithoutExtension(path);
 
-         }
 
-         public bool IsPathFile(string path)
 
-         {
 
-             // Cannot use Path.IsPathRooted because it returns false under mono when using windows-based paths, e.g. C:\\
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return true;
 
-             }
 
-             if (path.IndexOf("://", StringComparison.OrdinalIgnoreCase) != -1 &&
 
-                 !path.StartsWith("file://", StringComparison.OrdinalIgnoreCase))
 
-             {
 
-                 return false;
 
-             }
 
-             return true;
 
-             //return Path.IsPathRooted(path);
 
-         }
 
-         public void DeleteFile(string path)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 _sharpCifsFileSystem.DeleteFile(path);
 
-                 return;
 
-             }
 
-             SetAttributes(path, false, false);
 
-             File.Delete(path);
 
-         }
 
-         public void DeleteDirectory(string path, bool recursive)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 _sharpCifsFileSystem.DeleteDirectory(path, recursive);
 
-                 return;
 
-             }
 
-             Directory.Delete(path, recursive);
 
-         }
 
-         public void CreateDirectory(string path)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 _sharpCifsFileSystem.CreateDirectory(path);
 
-                 return;
 
-             }
 
-             Directory.CreateDirectory(path);
 
-         }
 
-         public List<FileSystemMetadata> GetDrives()
 
-         {
 
-             // Only include drives in the ready state or this method could end up being very slow, waiting for drives to timeout
 
-             return DriveInfo.GetDrives().Where(d => d.IsReady).Select(d => new FileSystemMetadata
 
-             {
 
-                 Name = GetName(d),
 
-                 FullName = d.RootDirectory.FullName,
 
-                 IsDirectory = true
 
-             }).ToList();
 
-         }
 
-         private string GetName(DriveInfo drive)
 
-         {
 
-             return drive.Name;
 
-         }
 
-         public IEnumerable<FileSystemMetadata> GetDirectories(string path, bool recursive = false)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.GetDirectories(path, recursive);
 
-             }
 
-             var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
 
-             return ToMetadata(new DirectoryInfo(path).EnumerateDirectories("*", searchOption));
 
-         }
 
-         public IEnumerable<FileSystemMetadata> GetFiles(string path, bool recursive = false)
 
-         {
 
-             return GetFiles(path, null, false, recursive);
 
-         }
 
-         public IEnumerable<FileSystemMetadata> GetFiles(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.GetFiles(path, extensions, enableCaseSensitiveExtensions, recursive);
 
-             }
 
-             var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
 
-             // On linux and osx the search pattern is case sensitive
 
-             // If we're OK with case-sensitivity, and we're only filtering for one extension, then use the native method
 
-             if ((enableCaseSensitiveExtensions || _isEnvironmentCaseInsensitive) && extensions != null && extensions.Length == 1)
 
-             {
 
-                 return ToMetadata(new DirectoryInfo(path).EnumerateFiles("*" + extensions[0], searchOption));
 
-             }
 
-             var files = new DirectoryInfo(path).EnumerateFiles("*", searchOption);
 
-             if (extensions != null && extensions.Length > 0)
 
-             {
 
-                 files = files.Where(i =>
 
-                 {
 
-                     var ext = i.Extension;
 
-                     if (ext == null)
 
-                     {
 
-                         return false;
 
-                     }
 
-                     return extensions.Contains(ext, StringComparer.OrdinalIgnoreCase);
 
-                 });
 
-             }
 
-             return ToMetadata(files);
 
-         }
 
-         public IEnumerable<FileSystemMetadata> GetFileSystemEntries(string path, bool recursive = false)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.GetFileSystemEntries(path, recursive);
 
-             }
 
-             var directoryInfo = new DirectoryInfo(path);
 
-             var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
 
-             if (EnableSeparateFileAndDirectoryQueries)
 
-             {
 
-                 return ToMetadata(directoryInfo.EnumerateDirectories("*", searchOption))
 
-                                 .Concat(ToMetadata(directoryInfo.EnumerateFiles("*", searchOption)));
 
-             }
 
-             return ToMetadata(directoryInfo.EnumerateFileSystemInfos("*", searchOption));
 
-         }
 
-         private IEnumerable<FileSystemMetadata> ToMetadata(IEnumerable<FileSystemInfo> infos)
 
-         {
 
-             return infos.Select(GetFileSystemMetadata);
 
-         }
 
-         public string[] ReadAllLines(string path)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.ReadAllLines(path);
 
-             }
 
-             return File.ReadAllLines(path);
 
-         }
 
-         public void WriteAllLines(string path, IEnumerable<string> lines)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 _sharpCifsFileSystem.WriteAllLines(path, lines);
 
-                 return;
 
-             }
 
-             File.WriteAllLines(path, lines);
 
-         }
 
-         public Stream OpenRead(string path)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.OpenRead(path);
 
-             }
 
-             return File.OpenRead(path);
 
-         }
 
-         private void CopyFileUsingStreams(string source, string target, bool overwrite)
 
-         {
 
-             using (var sourceStream = OpenRead(source))
 
-             {
 
-                 using (var targetStream = GetFileStream(target, FileOpenMode.Create, FileAccessMode.Write, FileShareMode.Read))
 
-                 {
 
-                     sourceStream.CopyTo(targetStream);
 
-                 }
 
-             }
 
-         }
 
-         public void CopyFile(string source, string target, bool overwrite)
 
-         {
 
-             var enableSharpCifsForSource = _sharpCifsFileSystem.IsEnabledForPath(source);
 
-             if (enableSharpCifsForSource != _sharpCifsFileSystem.IsEnabledForPath(target))
 
-             {
 
-                 CopyFileUsingStreams(source, target, overwrite);
 
-                 return;
 
-             }
 
-             if (enableSharpCifsForSource)
 
-             {
 
-                 _sharpCifsFileSystem.CopyFile(source, target, overwrite);
 
-                 return;
 
-             }
 
-             File.Copy(source, target, overwrite);
 
-         }
 
-         public void MoveFile(string source, string target)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(source))
 
-             {
 
-                 _sharpCifsFileSystem.MoveFile(source, target);
 
-                 return;
 
-             }
 
-             File.Move(source, target);
 
-         }
 
-         public void MoveDirectory(string source, string target)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(source))
 
-             {
 
-                 _sharpCifsFileSystem.MoveDirectory(source, target);
 
-                 return;
 
-             }
 
-             Directory.Move(source, target);
 
-         }
 
-         public bool DirectoryExists(string path)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.DirectoryExists(path);
 
-             }
 
-             return Directory.Exists(path);
 
-         }
 
-         public bool FileExists(string path)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.FileExists(path);
 
-             }
 
-             return File.Exists(path);
 
-         }
 
-         public string ReadAllText(string path)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.ReadAllText(path);
 
-             }
 
-             return File.ReadAllText(path);
 
-         }
 
-         public byte[] ReadAllBytes(string path)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.ReadAllBytes(path);
 
-             }
 
-             return File.ReadAllBytes(path);
 
-         }
 
-         public void WriteAllText(string path, string text, Encoding encoding)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 _sharpCifsFileSystem.WriteAllText(path, text, encoding);
 
-                 return;
 
-             }
 
-             File.WriteAllText(path, text, encoding);
 
-         }
 
-         public void WriteAllText(string path, string text)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 _sharpCifsFileSystem.WriteAllText(path, text);
 
-                 return;
 
-             }
 
-             File.WriteAllText(path, text);
 
-         }
 
-         public void WriteAllBytes(string path, byte[] bytes)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 _sharpCifsFileSystem.WriteAllBytes(path, bytes);
 
-                 return;
 
-             }
 
-             File.WriteAllBytes(path, bytes);
 
-         }
 
-         public string ReadAllText(string path, Encoding encoding)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.ReadAllText(path, encoding);
 
-             }
 
-             return File.ReadAllText(path, encoding);
 
-         }
 
-         public IEnumerable<string> GetDirectoryPaths(string path, bool recursive = false)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.GetDirectoryPaths(path, recursive);
 
-             }
 
-             var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
 
-             return Directory.EnumerateDirectories(path, "*", searchOption);
 
-         }
 
-         public IEnumerable<string> GetFilePaths(string path, bool recursive = false)
 
-         {
 
-             return GetFilePaths(path, null, false, recursive);
 
-         }
 
-         public IEnumerable<string> GetFilePaths(string path, string[] extensions, bool enableCaseSensitiveExtensions, bool recursive = false)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.GetFilePaths(path, extensions, enableCaseSensitiveExtensions, recursive);
 
-             }
 
-             var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
 
-             // On linux and osx the search pattern is case sensitive
 
-             // If we're OK with case-sensitivity, and we're only filtering for one extension, then use the native method
 
-             if ((enableCaseSensitiveExtensions || _isEnvironmentCaseInsensitive) && extensions != null && extensions.Length == 1)
 
-             {
 
-                 return Directory.EnumerateFiles(path, "*" + extensions[0], searchOption);
 
-             }
 
-             var files = Directory.EnumerateFiles(path, "*", searchOption);
 
-             if (extensions != null && extensions.Length > 0)
 
-             {
 
-                 files = files.Where(i =>
 
-                 {
 
-                     var ext = Path.GetExtension(i);
 
-                     if (ext == null)
 
-                     {
 
-                         return false;
 
-                     }
 
-                     return extensions.Contains(ext, StringComparer.OrdinalIgnoreCase);
 
-                 });
 
-             }
 
-             return files;
 
-         }
 
-         public IEnumerable<string> GetFileSystemEntryPaths(string path, bool recursive = false)
 
-         {
 
-             if (_sharpCifsFileSystem.IsEnabledForPath(path))
 
-             {
 
-                 return _sharpCifsFileSystem.GetFileSystemEntryPaths(path, recursive);
 
-             }
 
-             var searchOption = recursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
 
-             return Directory.EnumerateFileSystemEntries(path, "*", searchOption);
 
-         }
 
-         public virtual void SetExecutable(string path)
 
-         {
 
-             if (_environmentInfo.OperatingSystem == MediaBrowser.Model.System.OperatingSystem.OSX)
 
-             {
 
-                 RunProcess("chmod", "+x \"" + path + "\"", GetDirectoryName(path));
 
-             }
 
-         }
 
-         private 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();
 
-             }
 
-         }
 
-     }
 
- }
 
 
  |