mirror of
https://github.com/osukey/osukey.git
synced 2025-07-02 08:49:59 +09:00
Move hard link helper functions to their own class
This commit is contained in:
@ -72,7 +72,7 @@ namespace osu.Game.Database
|
|||||||
string testExistingPath = stableStorage.GetFullPath(stableStorage.GetFiles(string.Empty).First());
|
string testExistingPath = stableStorage.GetFullPath(stableStorage.GetFiles(string.Empty).First());
|
||||||
string testDestinationPath = desktopGameHost.Storage.GetFullPath(test_filename);
|
string testDestinationPath = desktopGameHost.Storage.GetFullPath(test_filename);
|
||||||
|
|
||||||
return RealmFileStore.CreateHardLink(testDestinationPath, testExistingPath, IntPtr.Zero);
|
return HardLinkHelper.CreateHardLink(testDestinationPath, testExistingPath, IntPtr.Zero);
|
||||||
}
|
}
|
||||||
|
|
||||||
public virtual async Task<int> GetImportCount(StableContent content, CancellationToken cancellationToken)
|
public virtual async Task<int> GetImportCount(StableContent content, CancellationToken cancellationToken)
|
||||||
|
@ -4,9 +4,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Runtime.InteropServices.ComTypes;
|
|
||||||
using Microsoft.Win32.SafeHandles;
|
|
||||||
using osu.Framework;
|
using osu.Framework;
|
||||||
using osu.Framework.Extensions;
|
using osu.Framework.Extensions;
|
||||||
using osu.Framework.IO.Stores;
|
using osu.Framework.IO.Stores;
|
||||||
@ -14,6 +11,7 @@ using osu.Framework.Logging;
|
|||||||
using osu.Framework.Platform;
|
using osu.Framework.Platform;
|
||||||
using osu.Framework.Testing;
|
using osu.Framework.Testing;
|
||||||
using osu.Game.Extensions;
|
using osu.Game.Extensions;
|
||||||
|
using osu.Game.IO;
|
||||||
using osu.Game.Models;
|
using osu.Game.Models;
|
||||||
using Realms;
|
using Realms;
|
||||||
|
|
||||||
@ -68,7 +66,7 @@ namespace osu.Game.Database
|
|||||||
if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows && data is FileStream fs && preferHardLinks)
|
if (RuntimeInfo.OS == RuntimeInfo.Platform.Windows && data is FileStream fs && preferHardLinks)
|
||||||
{
|
{
|
||||||
// attempt to do a fast hard link rather than copy.
|
// attempt to do a fast hard link rather than copy.
|
||||||
if (CreateHardLink(Storage.GetFullPath(file.GetStoragePath()), fs.Name, IntPtr.Zero))
|
if (HardLinkHelper.CreateHardLink(Storage.GetFullPath(file.GetStoragePath()), fs.Name, IntPtr.Zero))
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -128,63 +126,5 @@ namespace osu.Game.Database
|
|||||||
|
|
||||||
Logger.Log($@"Finished realm file store cleanup ({removedFiles} of {totalFiles} deleted)");
|
Logger.Log($@"Finished realm file store cleanup ({removedFiles} of {totalFiles} deleted)");
|
||||||
}
|
}
|
||||||
|
|
||||||
#region Windows hard link support
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
|
|
||||||
#endregion
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
68
osu.Game/IO/HardLinkHelper.cs
Normal file
68
osu.Game/IO/HardLinkHelper.cs
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. 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);
|
||||||
|
}
|
||||||
|
}
|
Reference in New Issue
Block a user