// Copyright (c) ppy Pty Ltd . Licensed under the MIT Licence. // See the LICENCE file in the repository root for full licence text. using System; using System.IO; using System.Runtime.InteropServices; using System.Runtime.InteropServices.ComTypes; using Microsoft.Win32.SafeHandles; namespace osu.Game.IO { internal static class HardLinkHelper { // For future use (to detect if a file is a hard link with other references existing on disk). 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); ByHandleFileInformation fileInfo; if (GetFileInformationByHandle(handle, out fileInfo)) result = (int)fileInfo.NumberOfLinks; CloseHandle(handle); return result; } [DllImport("Kernel32.dll", CharSet = CharSet.Unicode)] public static extern bool CreateHardLink( string lpFileName, string lpExistingFileName, IntPtr lpSecurityAttributes ); [StructLayout(LayoutKind.Sequential)] private struct ByHandleFileInformation { public readonly uint FileAttributes; public readonly FILETIME CreationTime; public readonly FILETIME LastAccessTime; public readonly FILETIME LastWriteTime; public readonly uint VolumeSerialNumber; public readonly uint FileSizeHigh; public readonly uint FileSizeLow; public readonly uint NumberOfLinks; public readonly uint FileIndexHigh; public readonly uint FileIndexLow; } [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)] private static extern bool GetFileInformationByHandle(SafeFileHandle handle, out ByHandleFileInformation lpFileInformation); [DllImport("kernel32.dll", SetLastError = true)] [return: MarshalAs(UnmanagedType.Bool)] private static extern bool CloseHandle(SafeHandle hObject); } }