123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233 |
-
- using Microsoft.Win32.SafeHandles;
- using System.Runtime.InteropServices;
- using System.Security.Cryptography;
- using System.Text;
- Console.WriteLine("Installer is suck");
- if (args.Length == 0)
- {
- Console.WriteLine("Usage: <inDir> <outDir>");
- return;
- }
- var dirIn = Path.GetFullPath(args[0]);
- var dirOut = Path.GetFullPath(args[1]);
- var files = Directory.GetFiles(dirIn);
- foreach (var file in files)
- {
- try
- {
- Console.WriteLine($"> {file}");
- var hl = HardLinkHelper.GetFileLinkCount(file);
- if (hl > 1)
- {
- Console.WriteLine(" SKIP");
- continue;
- }
- var info = new FileInfo(file);
- Console.WriteLine($" Len: {info.Length:N0}");
- Console.Write(" SHA256...");
- string hexHash;
- {
- using var inputStream = info.OpenRead();
- using var sha256 = SHA256.Create();
- var hash = sha256.ComputeHash(inputStream);
- hexHash = Convert.ToHexString(hash);
- }
- Console.WriteLine($" {hexHash}");
- var targetPath = Path.Combine(dirOut, $"{info.Length:0-000-000-000}_{hexHash}{info.Extension}");
- if (File.Exists(targetPath))
- {
- try
- {
- File.Delete(file);
- }
- catch (UnauthorizedAccessException)
- {
- Console.WriteLine($" Warn: Failure to delete {file}, moved to append ._del");
- File.Move(file, file + "._del");
- }
- }
- else
- {
- File.Move(file, targetPath);
- }
- HardLinkHelper.CreateHardLink(file, targetPath);
- Console.WriteLine($" Collapse to {targetPath} <");
- }
- catch (Exception e)
- {
- Console.WriteLine($"Error:{e.Message}");
- }
- Console.WriteLine();
- }
- public static class HardLinkHelper
- {
-
- [DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
- private static extern IntPtr FindFirstFileNameW(
- string lpFileName,
- uint dwFlags,
- ref uint lpdwBufferSize,
- StringBuilder lpLinkName
- );
- [DllImport("kernel32.dll", SetLastError = true)]
- private static extern bool FindNextFileNameW(
- IntPtr hFindStream,
- ref uint lpdwBufferSize,
- StringBuilder lpLinkName
- );
- [DllImport("kernel32.dll", SetLastError = true)]
- private static extern bool FindClose(IntPtr hFindStream);
- [DllImport("Kernel32.dll", CharSet = CharSet.Unicode)]
- private static extern bool CreateHardLink(
- string lpFileName,
- string lpExistingFileName,
- IntPtr lpSecurityAttributes
- );
- [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)]
- private static extern bool GetFileInformationByHandle(
- SafeFileHandle hFile,
- out BY_HANDLE_FILE_INFORMATION lpFileInformation
- );
- [StructLayout(LayoutKind.Sequential)]
- private struct BY_HANDLE_FILE_INFORMATION
- {
- public uint FileAttributes;
- public uint FileCreationTimeLow;
- public uint FileCreationTimeHigh;
- public uint LastAccessTimeLow;
- public uint LastAccessTimeHigh;
- public uint LastWriteTimeLow;
- public uint LastWriteTimeHigh;
- public uint VolumeSerialNumber;
- public uint FileSizeHigh;
- public uint FileSizeLow;
- public uint NumberOfLinks;
- public uint FileIndexHigh;
- public uint FileIndexLow;
- }
- [DllImport("kernel32.dll")]
- private static extern bool GetVolumePathName(string lpszFileName,
- [Out] StringBuilder lpszVolumePathName, uint cchBufferLength);
- [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
- private static extern SafeFileHandle CreateFile(
- string lpFileName,
- [MarshalAs(UnmanagedType.U4)] FileAccess dwDesiredAccess,
- [MarshalAs(UnmanagedType.U4)] FileShare dwShareMode,
- IntPtr lpSecurityAttributes,
- [MarshalAs(UnmanagedType.U4)] FileMode dwCreationDisposition,
- [MarshalAs(UnmanagedType.U4)] FileAttributes dwFlagsAndAttributes,
- IntPtr hTemplateFile);
- [DllImport("kernel32.dll", SetLastError = true)]
- [return: MarshalAs(UnmanagedType.Bool)]
- private static extern bool CloseHandle(SafeHandle hObject);
- [DllImport("shlwapi.dll", CharSet = CharSet.Auto)]
- private static extern bool PathAppend([In, Out] StringBuilder pszPath, string pszMore);
- public static bool CreateHardLink(string link, string to)
- {
- return CreateHardLink(link, to, nint.Zero);
- }
- public static int GetFileLinkCount(string filepath)
- {
- int result = 0;
- SafeFileHandle handle = CreateFile(filepath, FileAccess.Read, FileShare.Read, IntPtr.Zero, FileMode.Open, FileAttributes.Archive, IntPtr.Zero);
- BY_HANDLE_FILE_INFORMATION fileInfo = new BY_HANDLE_FILE_INFORMATION();
- if (GetFileInformationByHandle(handle, out fileInfo))
- result = (int)fileInfo.NumberOfLinks;
- CloseHandle(handle);
- return result;
- }
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- }
|