Nov
10th
Tue
10th
[Windows] Snapshot tool using hardlinks
using System;
using System.IO;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Rosids
{
class Program
{
static void Main(string[] args)
{
// @todo argument processer
var src = @"C:\Users\LiosK\Documents\Visual Studio 2008";
var lnk = @"C:\Users\LiosK\Desktop\Visual Studio 2008";
var dst = @"C:\Users\LiosK\Desktop\RosidsTest";
try
{
new Program(src, lnk, dst).Execute();
}
catch (Exception e)
{
Console.Error.WriteLine(e.Message);
}
}
readonly DirectoryInfo Source;
readonly DirectoryInfo LinkSource;
readonly DirectoryInfo Destination;
Program(string src, string lnk, string dst)
{
Source = new DirectoryInfo(src);
LinkSource = new DirectoryInfo(lnk);
Destination = new DirectoryInfo(dst);
}
void Execute()
{
CheckDirectories();
Destination.Create();
Visit(Source, LinkSource, Destination);
}
// Checks if Source, LinkSource and Destination satisfy assumptions.
void CheckDirectories()
{
if (!Source.Exists)
{
throw new ApplicationException("Source directory does not exist: " + Source.FullName);
}
if (!LinkSource.Exists)
{
throw new ApplicationException("Link source directory does not exist: " + LinkSource.FullName);
}
if (Destination.Exists)
{
if (Destination.GetFileSystemInfos().Length > 0)
{
throw new ApplicationException("Destination directory is not empty: " + Destination.FullName);
}
}
}
void Visit(DirectoryInfo src, DirectoryInfo lnk, DirectoryInfo dst)
{
if (!IsExcluded(src))
{
dst.Create();
foreach (var file in src.GetFiles())
{
try
{
if (!IsExcluded(file))
{
var lnkFile = Append(lnk, file);
if (IsSame(file, lnkFile))
{
// link
CreateHardLink(Append(dst, file).FullName, lnkFile.FullName, null);
Console.WriteLine("Linked: " + file.FullName);
}
else
{
// copy
file.CopyTo(Append(dst, file).FullName);
Console.WriteLine("Copied: " + file.FullName);
}
}
}
catch (Exception e)
{
// log and skip
Console.Error.WriteLine(e.Message + ": " + file.FullName);
}
}
foreach (var dir in src.GetDirectories())
{
try
{
Visit(dir, Append(lnk, dir), Append(dst, dir));
}
catch (Exception e)
{
// log and skip
Console.Error.WriteLine(e.Message + ": " + dir.FullName);
}
}
}
}
bool IsExcluded(DirectoryInfo src)
{
return false;
}
bool IsExcluded(FileInfo src)
{
return false;
}
bool IsSame(FileInfo src, FileInfo lnk)
{
return src.Exists && lnk.Exists && (src.Name == lnk.Name) && (src.Length == lnk.Length) && (src.LastWriteTimeUtc == lnk.LastWriteTimeUtc);
}
// shortcut function
private DirectoryInfo Append(DirectoryInfo dir, DirectoryInfo subdir)
{
return new DirectoryInfo(Path.Combine(dir.FullName, subdir.Name));
}
private FileInfo Append(DirectoryInfo dir, FileInfo file)
{
return new FileInfo(Path.Combine(dir.FullName, file.Name));
}
[DllImport("kernel32.dll")]
extern static bool CreateHardLink(string file, string existingFile, object secAttr);
}
}