mirror of
https://github.com/claunia/apprepodbmgr.git
synced 2025-12-16 19:24:42 +00:00
System.IO.EnumerateFiles follow symbolic links, creating an infinite
loop on links to "." and "..", so implement and use an enumerator that do not follow links.
This commit is contained in:
@@ -36,8 +36,10 @@ namespace osrepodbmgr.Core
|
||||
{
|
||||
public static List<string> files;
|
||||
public static List<string> folders;
|
||||
public static List<string> symlinks;
|
||||
public static Dictionary<string, DBOSFile> hashes;
|
||||
public static Dictionary<string, DBFolder> foldersDict;
|
||||
public static Dictionary<string, string> symlinksDict;
|
||||
public static string path;
|
||||
public static DBEntry dbInfo;
|
||||
public static bool unarUsable;
|
||||
@@ -54,7 +56,6 @@ namespace osrepodbmgr.Core
|
||||
public static bool usableDotNetZip;
|
||||
public static string clamdVersion;
|
||||
public static bool virusTotalEnabled;
|
||||
public static Dictionary<string, string> symlinks;
|
||||
|
||||
public delegate void UnarChangeStatusDelegate();
|
||||
public static event UnarChangeStatusDelegate UnarChangeStatus;
|
||||
|
||||
96
osrepodbmgr.Core/IO.cs
Normal file
96
osrepodbmgr.Core/IO.cs
Normal file
@@ -0,0 +1,96 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
|
||||
namespace osrepodbmgr.Core
|
||||
{
|
||||
public static class IO
|
||||
{
|
||||
public static List<string> EnumerateFiles(string path, string searchPattern, SearchOption searchOption, bool followLinks = true, bool symlinks = true)
|
||||
{
|
||||
if (followLinks)
|
||||
return new List<string>(Directory.EnumerateFiles(path, searchPattern, searchOption));
|
||||
|
||||
List<string> files = new List<string>();
|
||||
List<string> directories = new List<string>();
|
||||
|
||||
foreach (string file in Directory.EnumerateFiles(path, searchPattern))
|
||||
{
|
||||
FileInfo fi = new FileInfo(file);
|
||||
if (fi.Attributes.HasFlag(FileAttributes.ReparsePoint) && symlinks)
|
||||
files.Add(file);
|
||||
else if (!fi.Attributes.HasFlag(FileAttributes.ReparsePoint))
|
||||
files.Add(file);
|
||||
}
|
||||
|
||||
if (searchOption == SearchOption.AllDirectories)
|
||||
{
|
||||
foreach (string directory in Directory.EnumerateDirectories(path, searchPattern))
|
||||
{
|
||||
DirectoryInfo di = new DirectoryInfo(directory);
|
||||
if (!di.Attributes.HasFlag(FileAttributes.ReparsePoint))
|
||||
files.AddRange(EnumerateFiles(directory, searchPattern, searchOption, followLinks, symlinks));
|
||||
}
|
||||
}
|
||||
|
||||
return files;
|
||||
}
|
||||
|
||||
public static List<string> EnumerateDirectories(string path, string searchPattern, SearchOption searchOption, bool followLinks = true, bool symlinks = true)
|
||||
{
|
||||
if (followLinks)
|
||||
return new List<string>(Directory.EnumerateDirectories(path, searchPattern, searchOption));
|
||||
|
||||
List<string> directories = new List<string>();
|
||||
|
||||
if (searchOption == SearchOption.AllDirectories)
|
||||
{
|
||||
foreach (string directory in Directory.EnumerateDirectories(path, searchPattern))
|
||||
{
|
||||
DirectoryInfo di = new DirectoryInfo(directory);
|
||||
if (!di.Attributes.HasFlag(FileAttributes.ReparsePoint))
|
||||
directories.Add(directory);
|
||||
}
|
||||
|
||||
List<string> newDirectories = new List<string>();
|
||||
|
||||
foreach (string directory in directories)
|
||||
newDirectories.AddRange(EnumerateDirectories(directory, searchPattern, searchOption, followLinks, symlinks));
|
||||
|
||||
directories.AddRange(newDirectories);
|
||||
}
|
||||
|
||||
return directories;
|
||||
}
|
||||
|
||||
public static List<string> EnumerateSymlinks(string path, string searchPattern, SearchOption searchOption)
|
||||
{
|
||||
List<string> links = new List<string>();
|
||||
List<string> directories = new List<string>();
|
||||
|
||||
foreach (string file in Directory.EnumerateFiles(path, searchPattern))
|
||||
{
|
||||
FileInfo fi = new FileInfo(file);
|
||||
if (fi.Attributes.HasFlag(FileAttributes.ReparsePoint))
|
||||
links.Add(file);
|
||||
}
|
||||
|
||||
if (searchOption == SearchOption.AllDirectories)
|
||||
{
|
||||
foreach (string directory in Directory.EnumerateDirectories(path, searchPattern))
|
||||
{
|
||||
DirectoryInfo di = new DirectoryInfo(directory);
|
||||
if (!di.Attributes.HasFlag(FileAttributes.ReparsePoint))
|
||||
directories.Add(directory);
|
||||
else //if (!links.Contains(directory))
|
||||
links.Add(directory);
|
||||
}
|
||||
|
||||
foreach (string directory in directories)
|
||||
links.AddRange(EnumerateSymlinks(directory, searchPattern, searchOption));
|
||||
}
|
||||
|
||||
return links;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -296,13 +296,13 @@ namespace osrepodbmgr.Core
|
||||
stopwatch.Restart();
|
||||
#endif
|
||||
counter = 0;
|
||||
if(Context.symlinks.Count > 0)
|
||||
if(Context.symlinksDict.Count > 0)
|
||||
dbCore.DBOps.CreateSymlinkTableForOS(Context.dbInfo.id);
|
||||
|
||||
foreach(KeyValuePair<string, string> kvp in Context.symlinks)
|
||||
foreach(KeyValuePair<string, string> kvp in Context.symlinksDict)
|
||||
{
|
||||
if(UpdateProgress != null)
|
||||
UpdateProgress(null, "Adding symbolic links to OS in database", counter, Context.symlinks.Count);
|
||||
UpdateProgress(null, "Adding symbolic links to OS in database", counter, Context.symlinksDict.Count);
|
||||
|
||||
dbCore.DBOps.AddSymlinkToOS(kvp.Key, kvp.Value, Context.dbInfo.id);
|
||||
|
||||
|
||||
@@ -71,18 +71,25 @@ namespace osrepodbmgr.Core
|
||||
#if DEBUG
|
||||
stopwatch.Restart();
|
||||
#endif
|
||||
Context.files = new List<string>(Directory.EnumerateFiles(filesPath, "*", SearchOption.AllDirectories));
|
||||
Context.files = IO.EnumerateFiles(filesPath, "*", SearchOption.AllDirectories, false, false);
|
||||
Context.files.Sort();
|
||||
#if DEBUG
|
||||
stopwatch.Stop();
|
||||
Console.WriteLine("Core.FindFiles(): Took {0} seconds to find all files", stopwatch.Elapsed.TotalSeconds);
|
||||
stopwatch.Restart();
|
||||
#endif
|
||||
Context.folders = new List<string>(Directory.EnumerateDirectories(filesPath, "*", SearchOption.AllDirectories));
|
||||
Context.folders = IO.EnumerateDirectories(filesPath, "*", SearchOption.AllDirectories, false, false);
|
||||
Context.folders.Sort();
|
||||
#if DEBUG
|
||||
stopwatch.Stop();
|
||||
Console.WriteLine("Core.FindFiles(): Took {0} seconds to find all folders", stopwatch.Elapsed.TotalSeconds);
|
||||
stopwatch.Restart();
|
||||
#endif
|
||||
Context.symlinks = IO.EnumerateSymlinks(filesPath, "*", SearchOption.AllDirectories);
|
||||
Context.symlinks.Sort();
|
||||
#if DEBUG
|
||||
stopwatch.Stop();
|
||||
Console.WriteLine("Core.FindFiles(): Took {0} seconds to find all symbolic links", stopwatch.Elapsed.TotalSeconds);
|
||||
#endif
|
||||
if(Finished != null)
|
||||
Finished();
|
||||
@@ -107,14 +114,9 @@ namespace osrepodbmgr.Core
|
||||
{
|
||||
Context.hashes = new Dictionary<string, DBOSFile>();
|
||||
Context.foldersDict = new Dictionary<string, DBFolder>();
|
||||
Context.symlinks = new Dictionary<string, string>();
|
||||
Context.symlinksDict = new Dictionary<string, string>();
|
||||
List<string> alreadyMetadata = new List<string>();
|
||||
bool foundMetadata = false;
|
||||
bool symlinksSupported = DetectOS.GetRealPlatformID() != DiscImageChef.Interop.PlatformID.WinCE &&
|
||||
DetectOS.GetRealPlatformID() != DiscImageChef.Interop.PlatformID.Win32S &&
|
||||
DetectOS.GetRealPlatformID() != DiscImageChef.Interop.PlatformID.Win32NT &&
|
||||
DetectOS.GetRealPlatformID() != DiscImageChef.Interop.PlatformID.Win32Windows &&
|
||||
DetectOS.GetRealPlatformID() != DiscImageChef.Interop.PlatformID.WindowsPhone;
|
||||
|
||||
// For metadata
|
||||
List<ArchitecturesTypeArchitecture> architectures = new List<ArchitecturesTypeArchitecture>();
|
||||
@@ -141,6 +143,18 @@ namespace osrepodbmgr.Core
|
||||
|
||||
// End for metadata
|
||||
|
||||
if ((DetectOS.GetRealPlatformID() == DiscImageChef.Interop.PlatformID.WinCE ||
|
||||
DetectOS.GetRealPlatformID() == DiscImageChef.Interop.PlatformID.Win32S ||
|
||||
DetectOS.GetRealPlatformID() == DiscImageChef.Interop.PlatformID.Win32NT ||
|
||||
DetectOS.GetRealPlatformID() == DiscImageChef.Interop.PlatformID.Win32Windows ||
|
||||
DetectOS.GetRealPlatformID() == DiscImageChef.Interop.PlatformID.WindowsPhone) &&
|
||||
Context.symlinks.Count > 0)
|
||||
{
|
||||
if (Failed != null)
|
||||
Failed("Source contain unsupported symbolic links, not continuing.");
|
||||
return;
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
stopwatch.Restart();
|
||||
#endif
|
||||
@@ -362,32 +376,6 @@ namespace osrepodbmgr.Core
|
||||
|
||||
string relpath = file.Substring(filesPath.Length + 1);
|
||||
|
||||
if(fi.Attributes.HasFlag(FileAttributes.ReparsePoint))
|
||||
{
|
||||
// TODO: Symlinks not supported on any Windows platform
|
||||
if(!symlinksSupported)
|
||||
{
|
||||
if(Failed != null)
|
||||
Failed(string.Format("{0} is an unsupported symbolic link, not continuing.", relpath));
|
||||
return;
|
||||
}
|
||||
|
||||
if(UpdateProgress != null)
|
||||
UpdateProgress(string.Format("Resolving symlink on file {0} of {1}", counter, Context.files.Count), null, counter, Context.files.Count);
|
||||
|
||||
string target = Symlinks.ReadLink(file);
|
||||
if(target == null)
|
||||
{
|
||||
if(Failed != null)
|
||||
Failed(string.Format("Could not resolve symbolic link at {0}, not continuing.", relpath));
|
||||
return;
|
||||
}
|
||||
|
||||
Context.symlinks.Add(relpath, target);
|
||||
counter++;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(UpdateProgress != null)
|
||||
UpdateProgress(string.Format("Hashing file {0} of {1}", counter, Context.files.Count), null, counter, Context.files.Count);
|
||||
FileStream fileStream = new FileStream(file, FileMode.Open, FileAccess.Read);
|
||||
@@ -451,7 +439,6 @@ namespace osrepodbmgr.Core
|
||||
counter = 1;
|
||||
foreach(string folder in Context.folders)
|
||||
{
|
||||
|
||||
string filesPath;
|
||||
DirectoryInfo di = new DirectoryInfo(folder);
|
||||
|
||||
@@ -477,6 +464,38 @@ namespace osrepodbmgr.Core
|
||||
#if DEBUG
|
||||
stopwatch.Stop();
|
||||
Console.WriteLine("Core.HashFiles(): Took {0} seconds to iterate all folders", stopwatch.Elapsed.TotalSeconds);
|
||||
stopwatch.Restart();
|
||||
#endif
|
||||
counter = 2;
|
||||
foreach (string symlink in Context.symlinks)
|
||||
{
|
||||
string filesPath;
|
||||
|
||||
if (!string.IsNullOrEmpty(Context.tmpFolder) && Directory.Exists(Context.tmpFolder))
|
||||
filesPath = Context.tmpFolder;
|
||||
else
|
||||
filesPath = Context.path;
|
||||
|
||||
string relpath = symlink.Substring(filesPath.Length + 1);
|
||||
|
||||
if (UpdateProgress != null)
|
||||
UpdateProgress(string.Format("Resolving symlink {0} of {1}", counter, Context.symlinks.Count), null, counter, Context.symlinks.Count);
|
||||
|
||||
string target = Symlinks.ReadLink(symlink);
|
||||
if (target == null)
|
||||
{
|
||||
if (Failed != null)
|
||||
Failed(string.Format("Could not resolve symbolic link at {0}, not continuing.", relpath));
|
||||
return;
|
||||
}
|
||||
|
||||
Context.symlinksDict.Add(relpath, target);
|
||||
counter++;
|
||||
continue;
|
||||
}
|
||||
#if DEBUG
|
||||
stopwatch.Stop();
|
||||
Console.WriteLine("Core.HashFiles(): Took {0} seconds to resolve all symbolic links", stopwatch.Elapsed.TotalSeconds);
|
||||
#endif
|
||||
|
||||
if(foundMetadata)
|
||||
|
||||
@@ -77,6 +77,7 @@
|
||||
<Compile Include="Workers\Clamd.cs" />
|
||||
<Compile Include="Workers\VirusTotal.cs" />
|
||||
<Compile Include="Symlinks.cs" />
|
||||
<Compile Include="IO.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="packages.config" />
|
||||
|
||||
Reference in New Issue
Block a user