/// <summary> /// Do the linking of one file /// Ensures that duplicate link limits are not exceeded /// </summary> /// <param name="file">The DuplicateFile to link into one</param> static void LinkDuplicates(DuplicateFile file) { file.instances.Sort(); var newExtension = ".DVSLINKER.BAK"; string prefix = "\\\\?\\"; // @"\?"; var orig = prefix + file.instances[0]; uint links = GetLinks(file); for (int n = 1; n < file.instances.Count; n++, links++) { if (links >= 1023) { orig = prefix + file.instances[n]; links = GetLinks(file.instances[n]) - 1; //for loops adds 1 back on } else { var backup = file.instances[n] + newExtension; try { if (File.Exists(backup)) { File.Delete(backup); } File.Copy(file.instances[n], backup); //backup File.Delete(file.instances[n]); } catch { if (!File.Exists(file.instances[n])) { if (File.Exists(backup)) { File.Copy(backup, file.instances[n]); File.Delete(backup); } } continue; } var path = prefix + file.instances[n]; if (!Dll.CreateHardLink(path, orig, IntPtr.Zero)) { uint error = Dll.GetLastError(); //Marshal.GetLastWin32Error(); Debug.WriteLine("ERROR: " + error); File.Copy(backup, file.instances[n]); //restore backup File.Delete(backup); } else { File.Delete(backup); //remove backup because HardLink worked } } } }
/// <summary> /// Gets the number of HardLinks of a given <paramref name="filePath"/> /// </summary> /// <param name="filePath">Path to the file</param> /// <returns></returns> static uint GetLinks(string filePath) { //try { using (var f = new FileStream(filePath, FileMode.Open, FileAccess.Read)) { Dll.GetFileInformationByHandle(f.Handle, out var info); return(info.NumberOfLinks); } //} //catch { // return uint.MaxValue; //} }