Browse Source

fixes #200 - MB3 Locking Folders for a long time

Luke Pulverenti 12 years ago
parent
commit
b443d591a2
33 changed files with 245 additions and 396 deletions
  1. 1 1
      MediaBrowser.Api/EnvironmentService.cs
  2. 1 1
      MediaBrowser.Api/Playback/Hls/BaseHlsService.cs
  3. 2 2
      MediaBrowser.Controller/Drawing/ImageManager.cs
  4. 1 1
      MediaBrowser.Controller/Dto/DtoBuilder.cs
  5. 14 17
      MediaBrowser.Controller/Entities/BaseItem.cs
  6. 1 1
      MediaBrowser.Controller/Entities/Folder.cs
  7. 3 3
      MediaBrowser.Controller/Entities/Movies/Movie.cs
  8. 4 3
      MediaBrowser.Controller/Entities/TV/Season.cs
  9. 3 2
      MediaBrowser.Controller/Entities/TV/Series.cs
  10. 23 67
      MediaBrowser.Controller/IO/FileData.cs
  11. 41 118
      MediaBrowser.Controller/IO/FileSystem.cs
  12. 4 3
      MediaBrowser.Controller/Library/ILibraryManager.cs
  13. 30 30
      MediaBrowser.Controller/Library/ItemResolveArgs.cs
  14. 8 7
      MediaBrowser.Controller/Library/TVUtils.cs
  15. 3 3
      MediaBrowser.Controller/Providers/FolderProviderFromXml.cs
  16. 30 29
      MediaBrowser.Controller/Providers/ImageFromMediaLocationProvider.cs
  17. 14 48
      MediaBrowser.Controller/Providers/ImagesByNameProvider.cs
  18. 5 4
      MediaBrowser.Controller/Providers/MediaInfo/FFProbeVideoInfoProvider.cs
  19. 3 3
      MediaBrowser.Controller/Providers/Movies/MovieProviderFromJson.cs
  20. 3 3
      MediaBrowser.Controller/Providers/Movies/MovieProviderFromXml.cs
  21. 1 1
      MediaBrowser.Controller/Providers/Movies/PersonProviderFromJson.cs
  22. 3 3
      MediaBrowser.Controller/Providers/Music/MusicArtistProviderFromJson.cs
  23. 7 6
      MediaBrowser.Controller/Providers/TV/EpisodeImageFromMediaLocationProvider.cs
  24. 3 3
      MediaBrowser.Controller/Providers/TV/EpisodeProviderFromXml.cs
  25. 3 3
      MediaBrowser.Controller/Providers/TV/SeriesProviderFromXml.cs
  26. 7 7
      MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs
  27. 2 2
      MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs
  28. 1 1
      MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs
  29. 13 13
      MediaBrowser.Server.Implementations/Library/LibraryManager.cs
  30. 1 1
      MediaBrowser.Server.Implementations/Library/ResolverHelper.cs
  31. 4 4
      MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs
  32. 1 1
      MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs
  33. 5 5
      MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs

+ 1 - 1
MediaBrowser.Api/EnvironmentService.cs

@@ -205,7 +205,7 @@ namespace MediaBrowser.Api
         /// <returns>IEnumerable{FileSystemEntryInfo}.</returns>
         private IEnumerable<FileSystemEntryInfo> GetFileSystemEntries(GetDirectoryContents request)
         {
-            var entries = new DirectoryInfo(request.Path).EnumerateFileSystemInfos("*", SearchOption.TopDirectoryOnly).Where(i =>
+            var entries = new DirectoryInfo(request.Path).EnumerateFileSystemInfos().Where(i =>
             {
                 if (i.Attributes.HasFlag(FileAttributes.System))
                 {

+ 1 - 1
MediaBrowser.Api/Playback/Hls/BaseHlsService.cs

@@ -200,7 +200,7 @@ namespace MediaBrowser.Api.Playback.Hls
             var directory = Path.GetDirectoryName(outputFilePath);
             var name = Path.GetFileNameWithoutExtension(outputFilePath);
 
-            var filesToDelete = Directory.EnumerateFiles(directory, "*", SearchOption.TopDirectoryOnly)
+            var filesToDelete = Directory.EnumerateFiles(directory)
                 .Where(f => f.IndexOf(name, StringComparison.OrdinalIgnoreCase) != -1)
                 .ToList();
 

+ 2 - 2
MediaBrowser.Controller/Drawing/ImageManager.cs

@@ -428,7 +428,7 @@ namespace MediaBrowser.Controller.Drawing
             var metaFileEntry = item.ResolveArgs.GetMetaFileByPath(imagePath);
 
             // If we didn't the metafile entry, check the Season
-            if (!metaFileEntry.HasValue)
+            if (metaFileEntry == null)
             {
                 var episode = item as Episode;
 
@@ -439,7 +439,7 @@ namespace MediaBrowser.Controller.Drawing
             }
 
             // See if we can avoid a file system lookup by looking for the file in ResolveArgs
-            return metaFileEntry == null ? File.GetLastWriteTimeUtc(imagePath) : metaFileEntry.Value.LastWriteTimeUtc;
+            return metaFileEntry == null ? File.GetLastWriteTimeUtc(imagePath) : metaFileEntry.LastWriteTimeUtc;
         }
 
         /// <summary>

+ 1 - 1
MediaBrowser.Controller/Dto/DtoBuilder.cs

@@ -212,7 +212,7 @@ namespace MediaBrowser.Controller.Dto
             var metaFileEntry = item.ResolveArgs.GetMetaFileByPath(path);
 
             // See if we can avoid a file system lookup by looking for the file in ResolveArgs
-            var dateModified = metaFileEntry == null ? File.GetLastWriteTimeUtc(path) : metaFileEntry.Value.LastWriteTimeUtc;
+            var dateModified = metaFileEntry == null ? File.GetLastWriteTimeUtc(path) : metaFileEntry.LastWriteTimeUtc;
 
             ImageSize size;
 

+ 14 - 17
MediaBrowser.Controller/Entities/BaseItem.cs

@@ -244,13 +244,13 @@ namespace MediaBrowser.Controller.Entities
 
             // Record the name of each file 
             // Need to sort these because accoring to msdn docs, our i/o methods are not guaranteed in any order
-            foreach (var file in ResolveArgs.FileSystemChildren.OrderBy(f => f.cFileName))
+            foreach (var file in ResolveArgs.FileSystemChildren.OrderBy(f => f.Name))
             {
-                sb.Append(file.cFileName);
+                sb.Append(file.Name);
             }
-            foreach (var file in ResolveArgs.MetadataFiles.OrderBy(f => f.cFileName))
+            foreach (var file in ResolveArgs.MetadataFiles.OrderBy(f => f.Name))
             {
-                sb.Append(file.cFileName);
+                sb.Append(file.Name);
             }
 
             return sb.ToString().GetMD5();
@@ -307,7 +307,7 @@ namespace MediaBrowser.Controller.Entities
         /// Resets the resolve args.
         /// </summary>
         /// <param name="pathInfo">The path info.</param>
-        public void ResetResolveArgs(WIN32_FIND_DATA? pathInfo)
+        public void ResetResolveArgs(FileSystemInfo pathInfo)
         {
             ResolveArgs = CreateResolveArgs(pathInfo);
         }
@@ -318,17 +318,14 @@ namespace MediaBrowser.Controller.Entities
         /// <param name="pathInfo">The path info.</param>
         /// <returns>ItemResolveArgs.</returns>
         /// <exception cref="System.IO.IOException">Unable to retrieve file system info for  + path</exception>
-        protected internal virtual ItemResolveArgs CreateResolveArgs(WIN32_FIND_DATA? pathInfo = null)
+        protected internal virtual ItemResolveArgs CreateResolveArgs(FileSystemInfo pathInfo = null)
         {
             var path = Path;
 
             // non file-system entries will not have a path
             if (LocationType != LocationType.FileSystem || string.IsNullOrEmpty(path))
             {
-                return new ItemResolveArgs(ConfigurationManager.ApplicationPaths)
-                {
-                    FileInfo = new WIN32_FIND_DATA()
-                };
+                return new ItemResolveArgs(ConfigurationManager.ApplicationPaths);
             }
 
             if (UseParentPathToCreateResolveArgs)
@@ -336,16 +333,16 @@ namespace MediaBrowser.Controller.Entities
                 path = System.IO.Path.GetDirectoryName(path);
             }
 
-            pathInfo = pathInfo ?? FileSystem.GetFileData(path);
+            pathInfo = pathInfo ?? FileSystem.GetFileSystemInfo(path);
 
-            if (!pathInfo.HasValue)
+            if (pathInfo == null || !pathInfo.Exists)
             {
                 throw new IOException("Unable to retrieve file system info for " + path);
             }
 
             var args = new ItemResolveArgs(ConfigurationManager.ApplicationPaths)
             {
-                FileInfo = pathInfo.Value,
+                FileInfo = pathInfo,
                 Path = path,
                 Parent = Parent
             };
@@ -735,11 +732,11 @@ namespace MediaBrowser.Controller.Entities
                 return new List<Trailer>();
             }
 
-            IEnumerable<WIN32_FIND_DATA> files;
+            IEnumerable<FileSystemInfo> files;
 
             try
             {
-                files = FileSystem.GetFiles(folder.Value.Path);
+                files = new DirectoryInfo(folder.FullName).EnumerateFiles();
             }
             catch (IOException ex)
             {
@@ -793,11 +790,11 @@ namespace MediaBrowser.Controller.Entities
                 return new List<Audio.Audio>();
             }
 
-            IEnumerable<WIN32_FIND_DATA> files;
+            IEnumerable<FileSystemInfo> files;
 
             try
             {
-                files = FileSystem.GetFiles(folder.Value.Path);
+                files = new DirectoryInfo(folder.FullName).EnumerateFiles();
             }
             catch (IOException ex)
             {

+ 1 - 1
MediaBrowser.Controller/Entities/Folder.cs

@@ -768,7 +768,7 @@ namespace MediaBrowser.Controller.Entities
         /// <returns>IEnumerable{BaseItem}.</returns>
         protected virtual IEnumerable<BaseItem> GetNonCachedChildren()
         {
-            IEnumerable<WIN32_FIND_DATA> fileSystemChildren;
+            IEnumerable<FileSystemInfo> fileSystemChildren;
 
             try
             {

+ 3 - 3
MediaBrowser.Controller/Entities/Movies/Movie.cs

@@ -115,7 +115,7 @@ namespace MediaBrowser.Controller.Entities.Movies
         /// <returns>IEnumerable{Video}.</returns>
         private IEnumerable<Video> LoadSpecialFeatures()
         {
-            WIN32_FIND_DATA? folder;
+            FileSystemInfo folder;
 
             try
             {
@@ -133,11 +133,11 @@ namespace MediaBrowser.Controller.Entities.Movies
                 return new List<Video>();
             }
 
-            IEnumerable<WIN32_FIND_DATA> files;
+            IEnumerable<FileSystemInfo> files;
 
             try
             {
-                files = FileSystem.GetFiles(folder.Value.Path);
+                files = new DirectoryInfo(folder.FullName).EnumerateFiles();
             }
             catch (IOException ex)
             {

+ 4 - 3
MediaBrowser.Controller/Entities/TV/Season.cs

@@ -1,4 +1,5 @@
 using System.Collections.Generic;
+using System.IO;
 using MediaBrowser.Common.Extensions;
 using MediaBrowser.Controller.IO;
 using MediaBrowser.Controller.Library;
@@ -134,9 +135,9 @@ namespace MediaBrowser.Controller.Entities.TV
         {
             var folder = args.GetFileSystemEntryByName("metadata");
 
-            if (folder.HasValue)
+            if (folder != null)
             {
-                args.AddMetadataFiles(FileSystem.GetFiles(folder.Value.Path));
+                args.AddMetadataFiles(new DirectoryInfo(folder.FullName).EnumerateFiles());
             }
         }
 
@@ -145,7 +146,7 @@ namespace MediaBrowser.Controller.Entities.TV
         /// </summary>
         /// <param name="pathInfo">The path info.</param>
         /// <returns>ItemResolveArgs.</returns>
-        protected internal override ItemResolveArgs CreateResolveArgs(WIN32_FIND_DATA? pathInfo = null)
+        protected internal override ItemResolveArgs CreateResolveArgs(FileSystemInfo pathInfo = null)
         {
             var args = base.CreateResolveArgs(pathInfo);
 

+ 3 - 2
MediaBrowser.Controller/Entities/TV/Series.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Common.Extensions;
+using System.IO;
+using MediaBrowser.Common.Extensions;
 using MediaBrowser.Controller.IO;
 using MediaBrowser.Controller.Library;
 using MediaBrowser.Controller.Localization;
@@ -68,7 +69,7 @@ namespace MediaBrowser.Controller.Entities.TV
         /// </summary>
         /// <param name="pathInfo">The path info.</param>
         /// <returns>ItemResolveArgs.</returns>
-        protected internal override ItemResolveArgs CreateResolveArgs(WIN32_FIND_DATA? pathInfo = null)
+        protected internal override ItemResolveArgs CreateResolveArgs(FileSystemInfo pathInfo = null)
         {
             var args = base.CreateResolveArgs(pathInfo);
 

+ 23 - 67
MediaBrowser.Controller/IO/FileData.cs

@@ -3,7 +3,7 @@ using MediaBrowser.Model.Logging;
 using System;
 using System.Collections.Generic;
 using System.IO;
-using System.Runtime.InteropServices;
+using System.Linq;
 
 namespace MediaBrowser.Controller.IO
 {
@@ -13,91 +13,47 @@ namespace MediaBrowser.Controller.IO
     public static class FileData
     {
         /// <summary>
-        /// Gets all file system entries within a foler
+        /// Gets the filtered file system entries.
         /// </summary>
         /// <param name="path">The path.</param>
         /// <param name="logger">The logger.</param>
         /// <param name="searchPattern">The search pattern.</param>
-        /// <param name="includeFiles">if set to <c>true</c> [include files].</param>
-        /// <param name="includeDirectories">if set to <c>true</c> [include directories].</param>
         /// <param name="flattenFolderDepth">The flatten folder depth.</param>
         /// <param name="resolveShortcuts">if set to <c>true</c> [resolve shortcuts].</param>
         /// <param name="args">The args.</param>
-        /// <returns>Dictionary{System.StringWIN32_FIND_DATA}.</returns>
-        /// <exception cref="System.ArgumentNullException"></exception>
-        /// <exception cref="System.IO.IOException">GetFileSystemEntries failed</exception>
-        public static Dictionary<string, WIN32_FIND_DATA> GetFilteredFileSystemEntries(string path, ILogger logger, string searchPattern = "*", bool includeFiles = true, bool includeDirectories = true, int flattenFolderDepth = 0, bool resolveShortcuts = true, ItemResolveArgs args = null)
+        /// <returns>Dictionary{System.StringFileSystemInfo}.</returns>
+        /// <exception cref="System.ArgumentNullException">path</exception>
+        public static Dictionary<string, FileSystemInfo> GetFilteredFileSystemEntries(string path, ILogger logger, string searchPattern = "*", int flattenFolderDepth = 0, bool resolveShortcuts = true, ItemResolveArgs args = null)
         {
             if (string.IsNullOrEmpty(path))
             {
-                throw new ArgumentNullException();
+                throw new ArgumentNullException("path");
             }
 
-            var lpFileName = Path.Combine(path, searchPattern);
+            var dict = new Dictionary<string, FileSystemInfo>(StringComparer.OrdinalIgnoreCase);
+            
+            var entries = new DirectoryInfo(path).EnumerateFileSystemInfos(searchPattern, SearchOption.TopDirectoryOnly)
+                .Where(i => !i.Attributes.HasFlag(FileAttributes.System) && !i.Name.Equals(".") && !i.Name.Equals(".."));
 
-            WIN32_FIND_DATA lpFindFileData;
-            var handle = NativeMethods.FindFirstFileEx(lpFileName, FINDEX_INFO_LEVELS.FindExInfoBasic, out lpFindFileData,
-                                          FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero, FindFirstFileExFlags.FIND_FIRST_EX_LARGE_FETCH);
-
-            if (handle == IntPtr.Zero)
-            {
-                int hr = Marshal.GetLastWin32Error();
-                if (hr != 2 && hr != 0x12)
-                {
-                    throw new IOException("GetFileSystemEntries failed");
-                }
-                return new Dictionary<string, WIN32_FIND_DATA>(StringComparer.OrdinalIgnoreCase);
-            }
-
-            var dict = new Dictionary<string, WIN32_FIND_DATA>(StringComparer.OrdinalIgnoreCase);
-
-            if (FileSystem.IncludeInFindFileOutput(lpFindFileData.cFileName, lpFindFileData.dwFileAttributes, includeFiles, includeDirectories))
+            foreach (var entry in entries)
             {
-                if (!string.IsNullOrEmpty(lpFindFileData.cFileName))
-                {
-                    lpFindFileData.Path = Path.Combine(path, lpFindFileData.cFileName);
-
-                    dict[lpFindFileData.Path] = lpFindFileData;
-                }
-            }
+                var isDirectory = entry.Attributes.HasFlag(FileAttributes.Directory);
 
-            while (NativeMethods.FindNextFile(handle, out lpFindFileData) != IntPtr.Zero)
-            {
-                // This is the one circumstance where we can completely disregard a file
-                if (lpFindFileData.IsSystemFile)
+                if (resolveShortcuts && FileSystem.IsShortcut(entry.FullName))
                 {
-                    continue;
-                }
-
-                // Filter out invalid entries
-                if (lpFindFileData.cFileName.Equals(".", StringComparison.OrdinalIgnoreCase))
-                {
-                    continue;
-                }
-                if (lpFindFileData.cFileName.Equals("..", StringComparison.OrdinalIgnoreCase))
-                {
-                    continue;
-                }
-
-                lpFindFileData.Path = Path.Combine(path, lpFindFileData.cFileName);
-
-                if (resolveShortcuts && FileSystem.IsShortcut(lpFindFileData.Path))
-                {
-                    var newPath = FileSystem.ResolveShortcut(lpFindFileData.Path);
+                    var newPath = FileSystem.ResolveShortcut(entry.FullName);
                     if (string.IsNullOrWhiteSpace(newPath))
                     {
                         //invalid shortcut - could be old or target could just be unavailable
-                        logger.Warn("Encountered invalid shortuct: " + lpFindFileData.Path);
+                        logger.Warn("Encountered invalid shortuct: " + entry.FullName);
                         continue;
                     }
-                    var data = FileSystem.GetFileData(newPath);
+                    var data = FileSystem.GetFileSystemInfo(newPath);
 
-                    if (data.HasValue)
+                    if (data.Exists)
                     {
-                        lpFindFileData = data.Value;
-
                         // Find out if the shortcut is pointing to a directory or file
-                        if (lpFindFileData.IsDirectory)
+                        if (data.Attributes.HasFlag(FileAttributes.Directory))
                         {
                             // add to our physical locations
                             if (args != null)
@@ -106,25 +62,25 @@ namespace MediaBrowser.Controller.IO
                             }
                         }
 
-                        dict[lpFindFileData.Path] = lpFindFileData;
+                        dict[data.FullName] = data;
                     }
                 }
-                else if (flattenFolderDepth > 0 && lpFindFileData.IsDirectory)
+                else if (flattenFolderDepth > 0 && isDirectory)
                 {
-                    foreach (var child in GetFilteredFileSystemEntries(lpFindFileData.Path, logger, flattenFolderDepth: flattenFolderDepth - 1, resolveShortcuts: resolveShortcuts))
+                    foreach (var child in GetFilteredFileSystemEntries(entry.FullName, logger, flattenFolderDepth: flattenFolderDepth - 1, resolveShortcuts: resolveShortcuts))
                     {
                         dict[child.Key] = child.Value;
                     }
                 }
                 else
                 {
-                    dict[lpFindFileData.Path] = lpFindFileData;
+                    dict[entry.FullName] = entry;
                 }
             }
 
-            NativeMethods.FindClose(handle);
             return dict;
         }
+
     }
 
 }

+ 41 - 118
MediaBrowser.Controller/IO/FileSystem.cs

@@ -1,8 +1,7 @@
-using System;
-using System.Collections.Generic;
+using MediaBrowser.Model.Logging;
+using System;
 using System.Collections.Specialized;
 using System.IO;
-using System.Runtime.InteropServices;
 using System.Text;
 
 namespace MediaBrowser.Controller.IO
@@ -13,153 +12,77 @@ namespace MediaBrowser.Controller.IO
     public static class FileSystem
     {
         /// <summary>
-        /// Gets information about a path
+        /// Gets the file system info.
         /// </summary>
         /// <param name="path">The path.</param>
-        /// <returns>System.Nullable{WIN32_FIND_DATA}.</returns>
-        /// <exception cref="System.ArgumentNullException">path</exception>
-        /// <exception cref="System.IO.IOException">GetFileData failed for  + path</exception>
-        public static WIN32_FIND_DATA? GetFileData(string path)
+        /// <returns>FileSystemInfo.</returns>
+        public static FileSystemInfo GetFileSystemInfo(string path)
         {
-            if (string.IsNullOrEmpty(path))
+            // Take a guess to try and avoid two file system hits, but we'll double-check by calling Exists
+            if (Path.HasExtension(path))
             {
-                throw new ArgumentNullException("path");
-            }
-
-            WIN32_FIND_DATA data;
-            var handle = NativeMethods.FindFirstFileEx(path, FINDEX_INFO_LEVELS.FindExInfoBasic, out data,
-                                          FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero, FindFirstFileExFlags.NONE);
+                var fileInfo = new FileInfo(path);
 
-            var getFilename = false;
-
-            if (handle == NativeMethods.INVALID_HANDLE_VALUE && !Path.HasExtension(path))
-            {
-                if (!path.EndsWith("*", StringComparison.OrdinalIgnoreCase))
+                if (fileInfo.Exists)
                 {
-                    NativeMethods.FindClose(handle);
-
-                    handle = NativeMethods.FindFirstFileEx(Path.Combine(path, "*"), FINDEX_INFO_LEVELS.FindExInfoBasic, out data,
-                                          FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero, FindFirstFileExFlags.NONE);
-
-                    getFilename = true;
+                    return fileInfo;
                 }
-            }
-
-            if (handle == IntPtr.Zero)
-            {
-                throw new IOException("GetFileData failed for " + path);
-            }
 
-            NativeMethods.FindClose(handle);
-
-            // According to MSDN documentation, this will default to 1601 for paths that don't exist.		
-            if (data.CreationTimeUtc.Year == 1601)
-            {
-                return null;
+                return new DirectoryInfo(path);
             }
-
-            if (getFilename)
+            else
             {
-                data.cFileName = Path.GetFileName(path);
-            }
+                var fileInfo = new DirectoryInfo(path);
 
-            data.Path = path;
-            return data;
-        }
+                if (fileInfo.Exists)
+                {
+                    return fileInfo;
+                }
 
-        /// <summary>
-        /// Gets all files within a folder
-        /// </summary>
-        /// <param name="path">The path.</param>
-        /// <param name="searchPattern">The search pattern.</param>
-        /// <returns>IEnumerable{WIN32_FIND_DATA}.</returns>
-        public static IEnumerable<WIN32_FIND_DATA> GetFiles(string path, string searchPattern = "*")
-        {
-            return GetFileSystemEntries(path, searchPattern, includeDirectories: false);
+                return new FileInfo(path);
+            }
         }
 
         /// <summary>
-        /// Gets all file system entries within a foler
+        /// Gets the creation time UTC.
         /// </summary>
-        /// <param name="path">The path.</param>
-        /// <param name="searchPattern">The search pattern.</param>
-        /// <param name="includeFiles">if set to <c>true</c> [include files].</param>
-        /// <param name="includeDirectories">if set to <c>true</c> [include directories].</param>
-        /// <returns>IEnumerable{WIN32_FIND_DATA}.</returns>
-        /// <exception cref="System.ArgumentNullException">path</exception>
-        /// <exception cref="System.IO.IOException">GetFileSystemEntries failed</exception>
-        public static IEnumerable<WIN32_FIND_DATA> GetFileSystemEntries(string path, string searchPattern = "*", bool includeFiles = true, bool includeDirectories = true)
+        /// <param name="info">The info.</param>
+        /// <param name="logger">The logger.</param>
+        /// <returns>DateTime.</returns>
+        public static DateTime GetLastWriteTimeUtc(FileSystemInfo info, ILogger logger)
         {
-            if (string.IsNullOrEmpty(path))
-            {
-                throw new ArgumentNullException("path");
-            }
-            
-            var lpFileName = Path.Combine(path, searchPattern);
-
-            WIN32_FIND_DATA lpFindFileData;
-            var handle = NativeMethods.FindFirstFileEx(lpFileName, FINDEX_INFO_LEVELS.FindExInfoBasic, out lpFindFileData,
-                                          FINDEX_SEARCH_OPS.FindExSearchNameMatch, IntPtr.Zero, FindFirstFileExFlags.FIND_FIRST_EX_LARGE_FETCH);
-
-            if (handle == IntPtr.Zero)
-            {
-                var hr = Marshal.GetLastWin32Error();
-                if (hr != 2 && hr != 0x12)
-                {
-                    throw new IOException("GetFileSystemEntries failed");
-                }
-                yield break;
-            }
+            // This could throw an error on some file systems that have dates out of range
 
-            if (IncludeInFindFileOutput(lpFindFileData.cFileName, lpFindFileData.dwFileAttributes, includeFiles, includeDirectories))
+            try
             {
-                lpFindFileData.Path = Path.Combine(path, lpFindFileData.cFileName);
-
-                yield return lpFindFileData;
+                return info.LastAccessTimeUtc;
             }
-
-            while (NativeMethods.FindNextFile(handle, out lpFindFileData) != IntPtr.Zero)
+            catch (Exception ex)
             {
-                if (IncludeInFindFileOutput(lpFindFileData.cFileName, lpFindFileData.dwFileAttributes, includeFiles, includeDirectories))
-                {
-                    lpFindFileData.Path = Path.Combine(path, lpFindFileData.cFileName);
-                    yield return lpFindFileData;
-                }
+                logger.ErrorException("Error determining LastAccessTimeUtc for {0}", ex, info.FullName);
+                return DateTime.MinValue;
             }
-
-            NativeMethods.FindClose(handle);
         }
 
         /// <summary>
-        /// Includes the in find file output.
+        /// Gets the creation time UTC.
         /// </summary>
-        /// <param name="cFileName">Name of the c file.</param>
-        /// <param name="attributes">The attributes.</param>
-        /// <param name="includeFiles">if set to <c>true</c> [include files].</param>
-        /// <param name="includeDirectories">if set to <c>true</c> [include directories].</param>
-        /// <returns><c>true</c> if XXXX, <c>false</c> otherwise</returns>
-        public static bool IncludeInFindFileOutput(string cFileName, FileAttributes attributes, bool includeFiles, bool includeDirectories)
+        /// <param name="info">The info.</param>
+        /// <param name="logger">The logger.</param>
+        /// <returns>DateTime.</returns>
+        public static DateTime GetCreationTimeUtc(FileSystemInfo info, ILogger logger)
         {
-            if (cFileName.Equals(".", StringComparison.OrdinalIgnoreCase))
-            {
-                return false;
-            }
-            if (cFileName.Equals("..", StringComparison.OrdinalIgnoreCase))
-            {
-                return false;
-            }
+            // This could throw an error on some file systems that have dates out of range
 
-            if (!includeFiles && !attributes.HasFlag(FileAttributes.Directory))
+            try
             {
-                return false;
+                return info.CreationTimeUtc;
             }
-
-            if (!includeDirectories && attributes.HasFlag(FileAttributes.Directory))
+            catch (Exception ex)
             {
-                return false;
+                logger.ErrorException("Error determining CreationTimeUtc for {0}", ex, info.FullName);
+                return DateTime.MinValue;
             }
-
-            return true;
         }
 
         /// <summary>

+ 4 - 3
MediaBrowser.Controller/Library/ILibraryManager.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.Entities;
+using System.IO;
+using MediaBrowser.Controller.Entities;
 using MediaBrowser.Controller.Entities.Audio;
 using MediaBrowser.Controller.IO;
 using MediaBrowser.Controller.Resolvers;
@@ -40,7 +41,7 @@ namespace MediaBrowser.Controller.Library
         /// <param name="fileInfo">The file info.</param>
         /// <returns>BaseItem.</returns>
         /// <exception cref="System.ArgumentNullException"></exception>
-        BaseItem ResolvePath(string path, Folder parent = null, WIN32_FIND_DATA? fileInfo = null);
+        BaseItem ResolvePath(string path, Folder parent = null, FileSystemInfo fileInfo = null);
 
         /// <summary>
         /// Resolves a set of files into a list of BaseItem
@@ -49,7 +50,7 @@ namespace MediaBrowser.Controller.Library
         /// <param name="files">The files.</param>
         /// <param name="parent">The parent.</param>
         /// <returns>List{``0}.</returns>
-        List<T> ResolvePaths<T>(IEnumerable<WIN32_FIND_DATA> files, Folder parent) 
+        List<T> ResolvePaths<T>(IEnumerable<FileSystemInfo> files, Folder parent) 
             where T : BaseItem;
 
         /// <summary>

+ 30 - 30
MediaBrowser.Controller/Library/ItemResolveArgs.cs

@@ -31,7 +31,7 @@ namespace MediaBrowser.Controller.Library
         /// Gets the file system children.
         /// </summary>
         /// <value>The file system children.</value>
-        public IEnumerable<WIN32_FIND_DATA> FileSystemChildren
+        public IEnumerable<FileSystemInfo> FileSystemChildren
         {
             get { return FileSystemDictionary.Values; }
         }
@@ -40,7 +40,7 @@ namespace MediaBrowser.Controller.Library
         /// Gets or sets the file system dictionary.
         /// </summary>
         /// <value>The file system dictionary.</value>
-        public Dictionary<string, WIN32_FIND_DATA> FileSystemDictionary { get; set; }
+        public Dictionary<string, FileSystemInfo> FileSystemDictionary { get; set; }
 
         /// <summary>
         /// Gets or sets the parent.
@@ -52,7 +52,7 @@ namespace MediaBrowser.Controller.Library
         /// Gets or sets the file info.
         /// </summary>
         /// <value>The file info.</value>
-        public WIN32_FIND_DATA FileInfo { get; set; }
+        public FileSystemInfo FileInfo { get; set; }
 
         /// <summary>
         /// Gets or sets the path.
@@ -68,7 +68,7 @@ namespace MediaBrowser.Controller.Library
         {
             get
             {
-                return FileInfo.dwFileAttributes.HasFlag(FileAttributes.Directory);
+                return FileInfo.Attributes.HasFlag(FileAttributes.Directory);
             }
         }
 
@@ -80,7 +80,7 @@ namespace MediaBrowser.Controller.Library
         {
             get
             {
-                return FileInfo.IsHidden;
+                return FileInfo.Attributes.HasFlag(FileAttributes.Hidden);
             }
         }
 
@@ -92,7 +92,7 @@ namespace MediaBrowser.Controller.Library
         {
             get
             {
-                return FileInfo.IsSystemFile;
+                return FileInfo.Attributes.HasFlag(FileAttributes.System);
             }
         }
 
@@ -112,7 +112,7 @@ namespace MediaBrowser.Controller.Library
                     return false;
                 }
 
-                var parentDir = FileInfo.Path != null ? System.IO.Path.GetDirectoryName(FileInfo.Path) ?? string.Empty : string.Empty;
+                var parentDir = System.IO.Path.GetDirectoryName(FileInfo.FullName) ?? string.Empty;
 
                 return (parentDir.Length > _appPaths.RootFolderPath.Length
                     && parentDir.StartsWith(_appPaths.RootFolderPath, StringComparison.OrdinalIgnoreCase));
@@ -187,13 +187,13 @@ namespace MediaBrowser.Controller.Library
         /// Store these to reduce disk access in Resolvers
         /// </summary>
         /// <value>The metadata file dictionary.</value>
-        private Dictionary<string, WIN32_FIND_DATA> MetadataFileDictionary { get; set; }
+        private Dictionary<string, FileSystemInfo> MetadataFileDictionary { get; set; }
 
         /// <summary>
         /// Gets the metadata files.
         /// </summary>
         /// <value>The metadata files.</value>
-        public IEnumerable<WIN32_FIND_DATA> MetadataFiles
+        public IEnumerable<FileSystemInfo> MetadataFiles
         {
             get
             {
@@ -202,7 +202,7 @@ namespace MediaBrowser.Controller.Library
                     return MetadataFileDictionary.Values;
                 }
 
-                return new WIN32_FIND_DATA[] {};
+                return new FileSystemInfo[] { };
             }
         }
 
@@ -213,21 +213,21 @@ namespace MediaBrowser.Controller.Library
         /// <exception cref="System.IO.FileNotFoundException"></exception>
         public void AddMetadataFile(string path)
         {
-            var file = FileSystem.GetFileData(path);
+            var file = FileSystem.GetFileSystemInfo(path);
 
-            if (!file.HasValue)
+            if (!file.Exists)
             {
                 throw new FileNotFoundException(path);
             }
 
-            AddMetadataFile(file.Value);
+            AddMetadataFile(file);
         }
 
         /// <summary>
         /// Adds the metadata file.
         /// </summary>
         /// <param name="fileInfo">The file info.</param>
-        public void AddMetadataFile(WIN32_FIND_DATA fileInfo)
+        public void AddMetadataFile(FileSystemInfo fileInfo)
         {
             AddMetadataFiles(new[] { fileInfo });
         }
@@ -237,7 +237,7 @@ namespace MediaBrowser.Controller.Library
         /// </summary>
         /// <param name="files">The files.</param>
         /// <exception cref="System.ArgumentNullException"></exception>
-        public void AddMetadataFiles(IEnumerable<WIN32_FIND_DATA> files)
+        public void AddMetadataFiles(IEnumerable<FileSystemInfo> files)
         {
             if (files == null)
             {
@@ -246,11 +246,11 @@ namespace MediaBrowser.Controller.Library
             
             if (MetadataFileDictionary == null)
             {
-                MetadataFileDictionary = new Dictionary<string, WIN32_FIND_DATA>(StringComparer.OrdinalIgnoreCase);
+                MetadataFileDictionary = new Dictionary<string, FileSystemInfo>(StringComparer.OrdinalIgnoreCase);
             }
             foreach (var file in files)
             {
-                MetadataFileDictionary[file.cFileName] = file;
+                MetadataFileDictionary[file.Name] = file;
             }
         }
 
@@ -258,9 +258,9 @@ namespace MediaBrowser.Controller.Library
         /// Gets the name of the file system entry by.
         /// </summary>
         /// <param name="name">The name.</param>
-        /// <returns>System.Nullable{WIN32_FIND_DATA}.</returns>
+        /// <returns>FileSystemInfo.</returns>
         /// <exception cref="System.ArgumentNullException"></exception>
-        public WIN32_FIND_DATA? GetFileSystemEntryByName(string name)
+        public FileSystemInfo GetFileSystemEntryByName(string name)
         {
             if (string.IsNullOrEmpty(name))
             {
@@ -274,9 +274,9 @@ namespace MediaBrowser.Controller.Library
         /// Gets the file system entry by path.
         /// </summary>
         /// <param name="path">The path.</param>
-        /// <returns>System.Nullable{WIN32_FIND_DATA}.</returns>
+        /// <returns>FileSystemInfo.</returns>
         /// <exception cref="System.ArgumentNullException"></exception>
-        public WIN32_FIND_DATA? GetFileSystemEntryByPath(string path)
+        public FileSystemInfo GetFileSystemEntryByPath(string path)
         {
             if (string.IsNullOrEmpty(path))
             {
@@ -285,7 +285,7 @@ namespace MediaBrowser.Controller.Library
             
             if (FileSystemDictionary != null)
             {
-                WIN32_FIND_DATA entry;
+                FileSystemInfo entry;
 
                 if (FileSystemDictionary.TryGetValue(path, out entry))
                 {
@@ -300,9 +300,9 @@ namespace MediaBrowser.Controller.Library
         /// Gets the meta file by path.
         /// </summary>
         /// <param name="path">The path.</param>
-        /// <returns>System.Nullable{WIN32_FIND_DATA}.</returns>
+        /// <returns>FileSystemInfo.</returns>
         /// <exception cref="System.ArgumentNullException"></exception>
-        public WIN32_FIND_DATA? GetMetaFileByPath(string path)
+        public FileSystemInfo GetMetaFileByPath(string path)
         {
             if (string.IsNullOrEmpty(path))
             {
@@ -311,7 +311,7 @@ namespace MediaBrowser.Controller.Library
             
             if (MetadataFileDictionary != null)
             {
-                WIN32_FIND_DATA entry;
+                FileSystemInfo entry;
 
                 if (MetadataFileDictionary.TryGetValue(System.IO.Path.GetFileName(path), out entry))
                 {
@@ -326,9 +326,9 @@ namespace MediaBrowser.Controller.Library
         /// Gets the name of the meta file by.
         /// </summary>
         /// <param name="name">The name.</param>
-        /// <returns>System.Nullable{WIN32_FIND_DATA}.</returns>
+        /// <returns>FileSystemInfo.</returns>
         /// <exception cref="System.ArgumentNullException"></exception>
-        public WIN32_FIND_DATA? GetMetaFileByName(string name)
+        public FileSystemInfo GetMetaFileByName(string name)
         {
             if (string.IsNullOrEmpty(name))
             {
@@ -337,7 +337,7 @@ namespace MediaBrowser.Controller.Library
             
             if (MetadataFileDictionary != null)
             {
-                WIN32_FIND_DATA entry;
+                FileSystemInfo entry;
 
                 if (MetadataFileDictionary.TryGetValue(name, out entry))
                 {
@@ -355,7 +355,7 @@ namespace MediaBrowser.Controller.Library
         /// <returns><c>true</c> if [contains meta file by name] [the specified name]; otherwise, <c>false</c>.</returns>
         public bool ContainsMetaFileByName(string name)
         {
-            return GetMetaFileByName(name).HasValue;
+            return GetMetaFileByName(name) != null;
         }
 
         /// <summary>
@@ -365,7 +365,7 @@ namespace MediaBrowser.Controller.Library
         /// <returns><c>true</c> if [contains file system entry by name] [the specified name]; otherwise, <c>false</c>.</returns>
         public bool ContainsFileSystemEntryByName(string name)
         {
-            return GetFileSystemEntryByName(name).HasValue;
+            return GetFileSystemEntryByName(name) != null;
         }
 
         #region Equality Overrides

+ 8 - 7
MediaBrowser.Controller/Library/TVUtils.cs

@@ -1,4 +1,5 @@
-using MediaBrowser.Controller.IO;
+using System.IO;
+using MediaBrowser.Controller.IO;
 using System;
 using System.Collections.Generic;
 using System.Linq;
@@ -154,21 +155,21 @@ namespace MediaBrowser.Controller.Library
         /// <param name="path">The path.</param>
         /// <param name="fileSystemChildren">The file system children.</param>
         /// <returns><c>true</c> if [is series folder] [the specified path]; otherwise, <c>false</c>.</returns>
-        public static bool IsSeriesFolder(string path, IEnumerable<WIN32_FIND_DATA> fileSystemChildren)
+        public static bool IsSeriesFolder(string path, IEnumerable<FileSystemInfo> fileSystemChildren)
         {
             // A folder with more than 3 non-season folders in will not becounted as a series
             var nonSeriesFolders = 0;
 
             foreach (var child in fileSystemChildren)
             {
-                if (child.IsHidden || child.IsSystemFile)
+                if (child.Attributes.HasFlag(FileAttributes.Hidden) || child.Attributes.HasFlag(FileAttributes.System))
                 {
                     continue;
                 }
 
-                if (child.IsDirectory)
+                if (child.Attributes.HasFlag(FileAttributes.Directory))
                 {
-                    if (IsSeasonFolder(child.Path))
+                    if (IsSeasonFolder(child.FullName))
                     {
                         return true;
                     }
@@ -182,8 +183,8 @@ namespace MediaBrowser.Controller.Library
                 }
                 else
                 {
-                    if (EntityResolutionHelper.IsVideoFile(child.Path) &&
-                        !string.IsNullOrEmpty(EpisodeNumberFromFile(child.Path, false)))
+                    if (EntityResolutionHelper.IsVideoFile(child.FullName) &&
+                        !string.IsNullOrEmpty(EpisodeNumberFromFile(child.FullName, false)))
                     {
                         return true;
                     }

+ 3 - 3
MediaBrowser.Controller/Providers/FolderProviderFromXml.cs

@@ -46,7 +46,7 @@ namespace MediaBrowser.Controller.Providers
         protected override DateTime CompareDate(BaseItem item)
         {
             var entry = item.MetaLocation != null ? item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, "folder.xml")) : null;
-            return entry != null ? entry.Value.LastWriteTimeUtc : DateTime.MinValue;
+            return entry != null ? entry.LastWriteTimeUtc : DateTime.MinValue;
         }
 
         /// <summary>
@@ -73,9 +73,9 @@ namespace MediaBrowser.Controller.Providers
 
             var metadataFile = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, "folder.xml"));
 
-            if (metadataFile.HasValue)
+            if (metadataFile != null)
             {
-                var path = metadataFile.Value.Path;
+                var path = metadataFile.FullName;
 
                 await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
 

+ 30 - 29
MediaBrowser.Controller/Providers/ImageFromMediaLocationProvider.cs

@@ -17,7 +17,8 @@ namespace MediaBrowser.Controller.Providers
     /// </summary>
     public class ImageFromMediaLocationProvider : BaseMetadataProvider
     {
-        public ImageFromMediaLocationProvider(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager)
+        public ImageFromMediaLocationProvider(ILogManager logManager, IServerConfigurationManager configurationManager)
+            : base(logManager, configurationManager)
         {
         }
 
@@ -62,7 +63,7 @@ namespace MediaBrowser.Controller.Providers
         public override Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken)
         {
             cancellationToken.ThrowIfCancellationRequested();
-            
+
             // Make sure current image paths still exist
             ValidateImages(item);
 
@@ -72,7 +73,7 @@ namespace MediaBrowser.Controller.Providers
             ValidateBackdrops(item);
 
             cancellationToken.ThrowIfCancellationRequested();
-            
+
             PopulateBaseItemImages(item);
 
             SetLastRefreshed(item, DateTime.UtcNow);
@@ -95,11 +96,11 @@ namespace MediaBrowser.Controller.Providers
             {
                 var path = item.Images[image];
 
-                return IsInMetaLocation(item, path) && !item.ResolveArgs.GetMetaFileByPath(path).HasValue;
+                return IsInMetaLocation(item, path) && item.ResolveArgs.GetMetaFileByPath(path) == null;
             }).ToList();
 
             // Now remove them from the dictionary
-            foreach(var key in deletedKeys)
+            foreach (var key in deletedKeys)
             {
                 item.Images.Remove(key);
             }
@@ -117,7 +118,7 @@ namespace MediaBrowser.Controller.Providers
             }
 
             // Only validate paths from the same directory - need to copy to a list because we are going to potentially modify the collection below
-            var deletedImages = item.BackdropImagePaths.Where(path => IsInMetaLocation(item, path) && !item.ResolveArgs.GetMetaFileByPath(path).HasValue).ToList();
+            var deletedImages = item.BackdropImagePaths.Where(path => IsInMetaLocation(item, path) && item.ResolveArgs.GetMetaFileByPath(path) == null).ToList();
 
             // Now remove them from the dictionary
             foreach (var path in deletedImages)
@@ -143,7 +144,7 @@ namespace MediaBrowser.Controller.Providers
         /// <param name="item">The item.</param>
         /// <param name="filenameWithoutExtension">The filename without extension.</param>
         /// <returns>System.Nullable{WIN32_FIND_DATA}.</returns>
-        protected virtual WIN32_FIND_DATA? GetImage(BaseItem item, string filenameWithoutExtension)
+        protected virtual FileSystemInfo GetImage(BaseItem item, string filenameWithoutExtension)
         {
             return item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.ResolveArgs.Path, filenameWithoutExtension + ".png")) ?? item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.ResolveArgs.Path, filenameWithoutExtension + ".jpg"));
         }
@@ -160,65 +161,65 @@ namespace MediaBrowser.Controller.Providers
             // Primary Image
             var image = GetImage(item, "folder");
 
-            if (image.HasValue)
+            if (image != null)
             {
-                item.SetImage(ImageType.Primary, image.Value.Path);
+                item.SetImage(ImageType.Primary, image.FullName);
             }
 
             // Logo Image
             image = GetImage(item, "logo");
 
-            if (image.HasValue)
+            if (image != null)
             {
-                item.SetImage(ImageType.Logo, image.Value.Path);
+                item.SetImage(ImageType.Logo, image.FullName);
             }
 
             // Banner Image
             image = GetImage(item, "banner");
 
-            if (image.HasValue)
+            if (image != null)
             {
-                item.SetImage(ImageType.Banner, image.Value.Path);
+                item.SetImage(ImageType.Banner, image.FullName);
             }
 
             // Clearart
             image = GetImage(item, "clearart");
 
-            if (image.HasValue)
+            if (image != null)
             {
-                item.SetImage(ImageType.Art, image.Value.Path);
+                item.SetImage(ImageType.Art, image.FullName);
             }
 
             // Thumbnail Image
             image = GetImage(item, "thumb");
 
-            if (image.HasValue)
+            if (image != null)
             {
-                item.SetImage(ImageType.Thumb, image.Value.Path);
+                item.SetImage(ImageType.Thumb, image.FullName);
             }
 
             // Thumbnail Image
             image = GetImage(item, "box");
 
-            if (image.HasValue)
+            if (image != null)
             {
-                item.SetImage(ImageType.Box, image.Value.Path);
+                item.SetImage(ImageType.Box, image.FullName);
             }
 
             // Thumbnail Image
             image = GetImage(item, "menu");
 
-            if (image.HasValue)
+            if (image != null)
             {
-                item.SetImage(ImageType.Menu, image.Value.Path);
+                item.SetImage(ImageType.Menu, image.FullName);
             }
 
             // Backdrop Image
             image = GetImage(item, "backdrop");
 
-            if (image.HasValue)
+            if (image != null)
             {
-                backdropFiles.Add(image.Value.Path);
+                backdropFiles.Add(image.FullName);
             }
 
             var unfound = 0;
@@ -227,9 +228,9 @@ namespace MediaBrowser.Controller.Providers
                 // Backdrop Image
                 image = GetImage(item, "backdrop" + i);
 
-                if (image.HasValue)
+                if (image != null)
                 {
-                    backdropFiles.Add(image.Value.Path);
+                    backdropFiles.Add(image.FullName);
                 }
                 else
                 {
@@ -250,9 +251,9 @@ namespace MediaBrowser.Controller.Providers
             // Screenshot Image
             image = GetImage(item, "screenshot");
 
-            if (image.HasValue)
+            if (image != null)
             {
-                screenshotFiles.Add(image.Value.Path);
+                screenshotFiles.Add(image.FullName);
             }
 
             unfound = 0;
@@ -261,9 +262,9 @@ namespace MediaBrowser.Controller.Providers
                 // Screenshot Image
                 image = GetImage(item, "screenshot" + i);
 
-                if (image.HasValue)
+                if (image != null)
                 {
-                    screenshotFiles.Add(image.Value.Path);
+                    screenshotFiles.Add(image.FullName);
                 }
                 else
                 {

+ 14 - 48
MediaBrowser.Controller/Providers/ImagesByNameProvider.cs

@@ -88,7 +88,7 @@ namespace MediaBrowser.Controller.Providers
                 return DateTime.MinValue;
             }
 
-            var files = new DirectoryInfo(location).EnumerateFiles("*", SearchOption.TopDirectoryOnly).ToList();
+            var files = new DirectoryInfo(location).EnumerateFiles().ToList();
 
             if (files.Count == 0)
             {
@@ -97,54 +97,14 @@ namespace MediaBrowser.Controller.Providers
 
             return files.Select(f =>
             {
-                var lastWriteTime = GetLastWriteTimeUtc(f);
-                var creationTime = GetCreationTimeUtc(f);
+                var lastWriteTime = FileSystem.GetLastWriteTimeUtc(f, Logger);
+                var creationTime = FileSystem.GetCreationTimeUtc(f, Logger);
 
                 return creationTime > lastWriteTime ? creationTime : lastWriteTime;
 
             }).Max();
         }
 
-        /// <summary>
-        /// Gets the creation time UTC.
-        /// </summary>
-        /// <param name="info">The info.</param>
-        /// <returns>DateTime.</returns>
-        private DateTime GetLastWriteTimeUtc(FileSystemInfo info)
-        {
-            // This could throw an error on some file systems that have dates out of range
-
-            try
-            {
-                return info.LastAccessTimeUtc;
-            }
-            catch (Exception ex)
-            {
-                Logger.ErrorException("Error determining LastAccessTimeUtc for {0}", ex, info.FullName);
-                return DateTime.MinValue;
-            }
-        }
-
-        /// <summary>
-        /// Gets the creation time UTC.
-        /// </summary>
-        /// <param name="info">The info.</param>
-        /// <returns>DateTime.</returns>
-        private 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.ErrorException("Error determining CreationTimeUtc for {0}", ex, info.FullName);
-                return DateTime.MinValue;
-            }
-        }
-
         /// <summary>
         /// Fetches metadata and returns true or false indicating if any work that requires persistence was done
         /// </summary>
@@ -184,15 +144,21 @@ namespace MediaBrowser.Controller.Providers
         /// <param name="item">The item.</param>
         /// <param name="filenameWithoutExtension">The filename without extension.</param>
         /// <returns>System.Nullable{WIN32_FIND_DATA}.</returns>
-        protected override WIN32_FIND_DATA? GetImage(BaseItem item, string filenameWithoutExtension)
+        protected override FileSystemInfo GetImage(BaseItem item, string filenameWithoutExtension)
         {
             var location = GetLocation(item);
 
-            var result = FileSystem.GetFileData(Path.Combine(location, filenameWithoutExtension + ".png"));
-            if (!result.HasValue)
-                result = FileSystem.GetFileData(Path.Combine(location, filenameWithoutExtension + ".jpg"));
+            var result = new FileInfo(Path.Combine(location, filenameWithoutExtension + ".png"));
 
-            return result;
+            if (!result.Exists)
+                result = new FileInfo(Path.Combine(location, filenameWithoutExtension + ".jpg"));
+
+            if (result.Exists)
+            {
+                return result;
+            }
+
+            return null;
         }
     }
 }

+ 5 - 4
MediaBrowser.Controller/Providers/MediaInfo/FFProbeVideoInfoProvider.cs

@@ -255,16 +255,17 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
             var startIndex = video.MediaStreams == null ? 0 : video.MediaStreams.Count;
             var streams = new List<MediaStream>();
 
-            foreach (var file in fileSystemChildren.Where(f => !f.IsDirectory))
+            foreach (var file in fileSystemChildren.Where(f => !f.Attributes.HasFlag(FileAttributes.Directory)))
             {
-                var extension = Path.GetExtension(file.Path);
+                var fullName = file.FullName;
+                var extension = Path.GetExtension(fullName);
 
                 if (string.Equals(extension, ".srt", StringComparison.OrdinalIgnoreCase))
                 {
                     if (video.VideoType == VideoType.VideoFile)
                     {
                         // For video files the subtitle filename must match video filename
-                        if (!string.Equals(Path.GetFileNameWithoutExtension(video.Path), Path.GetFileNameWithoutExtension(file.Path)))
+                        if (!string.Equals(Path.GetFileNameWithoutExtension(video.Path), Path.GetFileNameWithoutExtension(fullName)))
                         {
                             continue;
                         }
@@ -275,7 +276,7 @@ namespace MediaBrowser.Controller.Providers.MediaInfo
                         Index = startIndex++,
                         Type = MediaStreamType.Subtitle,
                         IsExternal = true,
-                        Path = file.Path,
+                        Path = fullName,
                         Codec = "srt"
                     });
                 }

+ 3 - 3
MediaBrowser.Controller/Providers/Movies/MovieProviderFromJson.cs

@@ -47,7 +47,7 @@ namespace MediaBrowser.Controller.Providers.Movies
         protected override DateTime CompareDate(BaseItem item)
         {
             var entry = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, LOCAL_META_FILE_NAME));
-            return entry != null ? entry.Value.LastWriteTimeUtc : DateTime.MinValue;
+            return entry != null ? entry.LastWriteTimeUtc : DateTime.MinValue;
         }
 
         /// <summary>
@@ -84,10 +84,10 @@ namespace MediaBrowser.Controller.Providers.Movies
             cancellationToken.ThrowIfCancellationRequested();
 
             var entry = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, LOCAL_META_FILE_NAME));
-            if (entry.HasValue)
+            if (entry != null)
             {
                 // read in our saved meta and pass to processing function
-                var movieData = JsonSerializer.DeserializeFromFile<CompleteMovieData>(entry.Value.Path);
+                var movieData = JsonSerializer.DeserializeFromFile<CompleteMovieData>(entry.FullName);
 
                 cancellationToken.ThrowIfCancellationRequested();
 

+ 3 - 3
MediaBrowser.Controller/Providers/Movies/MovieProviderFromXml.cs

@@ -46,7 +46,7 @@ namespace MediaBrowser.Controller.Providers.Movies
         protected override DateTime CompareDate(BaseItem item)
         {
             var entry = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, "movie.xml"));
-            return entry != null ? entry.Value.LastWriteTimeUtc : DateTime.MinValue;
+            return entry != null ? entry.LastWriteTimeUtc : DateTime.MinValue;
         }
 
         /// <summary>
@@ -73,9 +73,9 @@ namespace MediaBrowser.Controller.Providers.Movies
             
             var metadataFile = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, "movie.xml"));
 
-            if (metadataFile.HasValue)
+            if (metadataFile != null)
             {
-                var path = metadataFile.Value.Path;
+                var path = metadataFile.FullName;
                 var boxset = item as BoxSet;
 
                 await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);

+ 1 - 1
MediaBrowser.Controller/Providers/Movies/PersonProviderFromJson.cs

@@ -68,7 +68,7 @@ namespace MediaBrowser.Controller.Providers.Movies
         protected override DateTime CompareDate(BaseItem item)
         {
             var entry = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation,MetaFileName));
-            return entry != null ? entry.Value.LastWriteTimeUtc : DateTime.MinValue;
+            return entry != null ? entry.LastWriteTimeUtc : DateTime.MinValue;
         }
 
         /// <summary>

+ 3 - 3
MediaBrowser.Controller/Providers/Music/MusicArtistProviderFromJson.cs

@@ -35,10 +35,10 @@ namespace MediaBrowser.Controller.Providers.Music
             cancellationToken.ThrowIfCancellationRequested();
 
             var entry = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, LastfmHelper.LocalArtistMetaFileName));
-            if (entry.HasValue)
+            if (entry != null)
             {
                 // read in our saved meta and pass to processing function
-                var data = JsonSerializer.DeserializeFromFile<LastfmArtist>(entry.Value.Path);
+                var data = JsonSerializer.DeserializeFromFile<LastfmArtist>(entry.FullName);
 
                 cancellationToken.ThrowIfCancellationRequested();
 
@@ -93,7 +93,7 @@ namespace MediaBrowser.Controller.Providers.Music
         protected override DateTime CompareDate(BaseItem item)
         {
             var entry = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, LastfmHelper.LocalArtistMetaFileName));
-            return entry != null ? entry.Value.LastWriteTimeUtc : DateTime.MinValue;
+            return entry != null ? entry.LastWriteTimeUtc : DateTime.MinValue;
         }
 
     }

+ 7 - 6
MediaBrowser.Controller/Providers/TV/EpisodeImageFromMediaLocationProvider.cs

@@ -15,7 +15,8 @@ namespace MediaBrowser.Controller.Providers.TV
     /// </summary>
     public class EpisodeImageFromMediaLocationProvider : BaseMetadataProvider
     {
-        public EpisodeImageFromMediaLocationProvider(ILogManager logManager, IServerConfigurationManager configurationManager) : base(logManager, configurationManager)
+        public EpisodeImageFromMediaLocationProvider(ILogManager logManager, IServerConfigurationManager configurationManager)
+            : base(logManager, configurationManager)
         {
         }
 
@@ -60,7 +61,7 @@ namespace MediaBrowser.Controller.Providers.TV
         public override Task<bool> FetchAsync(BaseItem item, bool force, CancellationToken cancellationToken)
         {
             cancellationToken.ThrowIfCancellationRequested();
-            
+
             var episode = (Episode)item;
 
             var episodeFileName = Path.GetFileName(episode.Path);
@@ -70,7 +71,7 @@ namespace MediaBrowser.Controller.Providers.TV
             ValidateImage(episode, item.MetaLocation);
 
             cancellationToken.ThrowIfCancellationRequested();
-            
+
             SetPrimaryImagePath(episode, parent, item.MetaLocation, episodeFileName);
 
             SetLastRefreshed(item, DateTime.UtcNow);
@@ -98,7 +99,7 @@ namespace MediaBrowser.Controller.Providers.TV
                 return;
             }
 
-            if (!episode.Parent.ResolveArgs.GetMetaFileByPath(path).HasValue)
+            if (episode.Parent.ResolveArgs.GetMetaFileByPath(path) == null)
             {
                 episode.PrimaryImagePath = null;
             }
@@ -122,9 +123,9 @@ namespace MediaBrowser.Controller.Providers.TV
             var file = parent.ResolveArgs.GetMetaFileByPath(imageFiles[0]) ??
                        parent.ResolveArgs.GetMetaFileByPath(imageFiles[1]);
 
-            if (file.HasValue)
+            if (file != null)
             {
-                item.PrimaryImagePath = file.Value.Path;
+                item.PrimaryImagePath = file.FullName;
             }
         }
     }

+ 3 - 3
MediaBrowser.Controller/Providers/TV/EpisodeProviderFromXml.cs

@@ -71,12 +71,12 @@ namespace MediaBrowser.Controller.Providers.TV
 
             var file = item.ResolveArgs.Parent.ResolveArgs.GetMetaFileByPath(metadataFile);
 
-            if (!file.HasValue)
+            if (file == null)
             {
                 return base.CompareDate(item);
             }
 
-            return file.Value.LastWriteTimeUtc;
+            return file.LastWriteTimeUtc;
         }
 
         /// <summary>
@@ -93,7 +93,7 @@ namespace MediaBrowser.Controller.Providers.TV
 
             var file = item.ResolveArgs.Parent.ResolveArgs.GetMetaFileByPath(metadataFile);
 
-            if (!file.HasValue)
+            if (file == null)
             {
                 return false;
             }

+ 3 - 3
MediaBrowser.Controller/Providers/TV/SeriesProviderFromXml.cs

@@ -47,7 +47,7 @@ namespace MediaBrowser.Controller.Providers.TV
         protected override DateTime CompareDate(BaseItem item)
         {
             var entry = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, "series.xml"));
-            return entry != null ? entry.Value.LastWriteTimeUtc : DateTime.MinValue;
+            return entry != null ? entry.LastWriteTimeUtc : DateTime.MinValue;
         }
 
         /// <summary>
@@ -74,9 +74,9 @@ namespace MediaBrowser.Controller.Providers.TV
             
             var metadataFile = item.ResolveArgs.GetMetaFileByPath(Path.Combine(item.MetaLocation, "series.xml"));
 
-            if (metadataFile.HasValue)
+            if (metadataFile != null)
             {
-                var path = metadataFile.Value.Path;
+                var path = metadataFile.FullName;
 
                 await XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
 

+ 7 - 7
MediaBrowser.Controller/Resolvers/EntityResolutionHelper.cs

@@ -72,19 +72,19 @@ namespace MediaBrowser.Controller.Resolvers
             {
                 var childData = args.IsDirectory ? args.GetFileSystemEntryByPath(item.Path) : null;
 
-                if (childData.HasValue)
+                if (childData != null)
                 {
-                    item.DateCreated = childData.Value.CreationTimeUtc;
-                    item.DateModified = childData.Value.LastWriteTimeUtc;
+                    item.DateCreated = childData.CreationTimeUtc;
+                    item.DateModified = childData.LastWriteTimeUtc;
                 }
                 else
                 {
-                    var fileData = FileSystem.GetFileData(item.Path);
+                    var fileData = FileSystem.GetFileSystemInfo(item.Path);
 
-                    if (fileData.HasValue)
+                    if (fileData.Exists)
                     {
-                        item.DateCreated = fileData.Value.CreationTimeUtc;
-                        item.DateModified = fileData.Value.LastWriteTimeUtc;
+                        item.DateCreated = fileData.CreationTimeUtc;
+                        item.DateModified = fileData.LastWriteTimeUtc;
                     }
                 }
             }

+ 2 - 2
MediaBrowser.Server.Implementations/IO/DirectoryWatchers.cs

@@ -394,9 +394,9 @@ namespace MediaBrowser.Server.Implementations.IO
         {
             try
             {
-                var data = FileSystem.GetFileData(path);
+                var data = FileSystem.GetFileSystemInfo(path);
 
-                if (!data.HasValue || data.Value.IsDirectory)
+                if (!data.Exists || data.Attributes.HasFlag(FileAttributes.Directory))
                 {
                     return false;
                 }

+ 1 - 1
MediaBrowser.Server.Implementations/Library/CoreResolutionIgnoreRule.cs

@@ -47,7 +47,7 @@ namespace MediaBrowser.Server.Implementations.Library
 
             if (args.IsDirectory)
             {
-                var filename = args.FileInfo.cFileName;
+                var filename = args.FileInfo.Name;
 
                 // Ignore any folders in our list
                 if (IgnoreFolders.Contains(filename, StringComparer.OrdinalIgnoreCase))

+ 13 - 13
MediaBrowser.Server.Implementations/Library/LibraryManager.cs

@@ -403,16 +403,16 @@ namespace MediaBrowser.Server.Implementations.Library
         /// <param name="fileInfo">The file info.</param>
         /// <returns>BaseItem.</returns>
         /// <exception cref="System.ArgumentNullException"></exception>
-        public BaseItem ResolvePath(string path, Folder parent = null, WIN32_FIND_DATA? fileInfo = null)
+        public BaseItem ResolvePath(string path, Folder parent = null, FileSystemInfo fileInfo = null)
         {
             if (string.IsNullOrEmpty(path))
             {
                 throw new ArgumentNullException();
             }
 
-            fileInfo = fileInfo ?? FileSystem.GetFileData(path);
+            fileInfo = fileInfo ?? FileSystem.GetFileSystemInfo(path);
 
-            if (!fileInfo.HasValue)
+            if (!fileInfo.Exists)
             {
                 return null;
             }
@@ -421,7 +421,7 @@ namespace MediaBrowser.Server.Implementations.Library
             {
                 Parent = parent,
                 Path = path,
-                FileInfo = fileInfo.Value
+                FileInfo = fileInfo
             };
 
             // Return null if ignore rules deem that we should do so
@@ -468,7 +468,7 @@ namespace MediaBrowser.Server.Implementations.Library
         /// <param name="files">The files.</param>
         /// <param name="parent">The parent.</param>
         /// <returns>List{``0}.</returns>
-        public List<T> ResolvePaths<T>(IEnumerable<WIN32_FIND_DATA> files, Folder parent)
+        public List<T> ResolvePaths<T>(IEnumerable<FileSystemInfo> files, Folder parent)
             where T : BaseItem
         {
             var list = new List<T>();
@@ -477,7 +477,7 @@ namespace MediaBrowser.Server.Implementations.Library
             {
                 try
                 {
-                    var item = ResolvePath(f.Path, parent, f) as T;
+                    var item = ResolvePath(f.FullName, parent, f) as T;
 
                     if (item != null)
                     {
@@ -489,7 +489,7 @@ namespace MediaBrowser.Server.Implementations.Library
                 }
                 catch (Exception ex)
                 {
-                    _logger.ErrorException("Error resolving path {0}", ex, f.Path);
+                    _logger.ErrorException("Error resolving path {0}", ex, f.FullName);
                 }
             });
 
@@ -680,16 +680,16 @@ namespace MediaBrowser.Server.Implementations.Library
 
             path = Path.Combine(path, FileSystem.GetValidFilename(name));
 
-            var fileInfo = FileSystem.GetFileData(path);
+            var fileInfo = new DirectoryInfo(path);
 
             var isNew = false;
 
-            if (!fileInfo.HasValue)
+            if (!fileInfo.Exists)
             {
                 Directory.CreateDirectory(path);
-                fileInfo = FileSystem.GetFileData(path);
+                fileInfo = new DirectoryInfo(path);
 
-                if (!fileInfo.HasValue)
+                if (!fileInfo.Exists)
                 {
                     throw new IOException("Path not created: " + path);
                 }
@@ -708,8 +708,8 @@ namespace MediaBrowser.Server.Implementations.Library
                 {
                     Name = name,
                     Id = id,
-                    DateCreated = fileInfo.Value.CreationTimeUtc,
-                    DateModified = fileInfo.Value.LastWriteTimeUtc,
+                    DateCreated = fileInfo.CreationTimeUtc,
+                    DateModified = fileInfo.LastWriteTimeUtc,
                     Path = path
                 };
                 isNew = true;

+ 1 - 1
MediaBrowser.Server.Implementations/Library/ResolverHelper.cs

@@ -53,7 +53,7 @@ namespace MediaBrowser.Server.Implementations.Library
             if (string.IsNullOrEmpty(item.Name) && !string.IsNullOrEmpty(item.Path))
             {
                 //we use our resolve args name here to get the name of the containg folder, not actual video file
-                item.Name = GetMBName(item.ResolveArgs.FileInfo.cFileName, item.ResolveArgs.FileInfo.IsDirectory);
+                item.Name = GetMBName(item.ResolveArgs.FileInfo.Name, item.ResolveArgs.FileInfo.Attributes.HasFlag(FileAttributes.Directory));
             }
         }
 

+ 4 - 4
MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicAlbumResolver.cs

@@ -49,7 +49,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
             // If list contains at least 2 audio files or at least one and no video files consider it to contain music
             var foundAudio = 0;
 
-            foreach (var fullName in new DirectoryInfo(path).EnumerateFiles("*", SearchOption.TopDirectoryOnly).Select(file => file.FullName))
+            foreach (var fullName in new DirectoryInfo(path).EnumerateFiles().Select(file => file.FullName))
             {
                 if (AudioResolver.IsAudioFile(fullName)) foundAudio++;
                 if (foundAudio >= 2)
@@ -86,19 +86,19 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
         /// </summary>
         /// <param name="list">The list.</param>
         /// <returns><c>true</c> if the specified list contains music; otherwise, <c>false</c>.</returns>
-        public static bool ContainsMusic(IEnumerable<WIN32_FIND_DATA> list)
+        public static bool ContainsMusic(IEnumerable<FileSystemInfo> list)
         {
             // If list contains at least 2 audio files or at least one and no video files consider it to contain music
             var foundAudio = 0;
 
             foreach (var file in list)
             {
-                if (AudioResolver.IsAudioFile(file.Path)) foundAudio++;
+                if (AudioResolver.IsAudioFile(file.FullName)) foundAudio++;
                 if (foundAudio >= 2)
                 {
                     return true;
                 }
-                if (EntityResolutionHelper.IsVideoFile(file.Path)) return false;
+                if (EntityResolutionHelper.IsVideoFile(file.FullName)) return false;
             }
 
             //  or a single audio file and no video files

+ 1 - 1
MediaBrowser.Server.Implementations/Library/Resolvers/Audio/MusicArtistResolver.cs

@@ -33,7 +33,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Audio
             if (args.Parent.IsRoot) return null;
 
             // If we contain an album assume we are an artist folder
-            return args.FileSystemChildren.Any(i => MusicAlbumResolver.IsMusicAlbum(i.Path)) ? new MusicArtist() : null;
+            return args.FileSystemChildren.Any(i => MusicAlbumResolver.IsMusicAlbum(i.FullName)) ? new MusicArtist() : null;
         }
 
     }

+ 5 - 5
MediaBrowser.Server.Implementations/Library/Resolvers/Movies/MovieResolver.cs

@@ -127,9 +127,9 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
             // Loop through each child file/folder and see if we find a video
             foreach (var child in args.FileSystemChildren)
             {
-                if (child.IsDirectory)
+                if (child.Attributes.HasFlag(FileAttributes.Directory))
                 {
-                    if (IsDvdDirectory(child.cFileName))
+                    if (IsDvdDirectory(child.Name))
                     {
                         return new Movie
                         {
@@ -137,7 +137,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
                             VideoType = VideoType.Dvd
                         };
                     }
-                    if (IsBluRayDirectory(child.cFileName))
+                    if (IsBluRayDirectory(child.Name))
                     {
                         return new Movie
                         {
@@ -145,7 +145,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
                             VideoType = VideoType.BluRay
                         };
                     }
-                    if (IsHdDvdDirectory(child.cFileName))
+                    if (IsHdDvdDirectory(child.Name))
                     {
                         return new Movie
                         {
@@ -160,7 +160,7 @@ namespace MediaBrowser.Server.Implementations.Library.Resolvers.Movies
                 var childArgs = new ItemResolveArgs(ApplicationPaths)
                 {
                     FileInfo = child,
-                    Path = child.Path
+                    Path = child.FullName
                 };
 
                 var item = base.Resolve(childArgs);