-
-
Notifications
You must be signed in to change notification settings - Fork 94
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implementing file linking for the client file system (#590)
* Replace `File.Copy` to `CreateSymbolicLink` for `KeepChanges` file option * Update config for test (revert commit latter) * Add check for OS platform and rename link method * Add handling exception if hard link isn't established * Add .NET 4.8 Linux method to create link * Move link logic to `ImmutableLink` and `Link` * Refactor link creation functions * Fix `source` and `destination` arguments for `CreateHardLink` and `CreateSymbolicLink` * Rename link operation to AlwaysOverwrite_Link * Fix careless CreateSymlinkFromSource call * Correct link and symlink definitions * Update config * Turn off readonly property when deleting * Revert making the source file readonly * Remove if in switch-case statement * Localize exception messages * Revert "Remove if in switch-case statement" This reverts commit a89f6a3. * Load libc from "libc.so.6" * Mark link methods as static * Enforce coding style * Prefer Marshal.ThrowExceptionForHR() * Remove symlink codes since the implementation requires a workaround for legacy Windows. Compared with the one in .NET 6 runtime, our implementation is not robust enough. * Update libc importing to align with dotnet/msbuild * Throw a specific exception * Rename `AlwaysOverwrite_Link` to `LinkAsReadOnly` and update `KeepChanges` Co-authored-by: Metadorius <[email protected]> * Move `CreateHardLinkFromSource` to `FileHelper` Co-authored-by: Metadorius <[email protected]> * Enable fallback by default * Improve translation game files with new linking method * Use new linking method to link `ddraw.dll` * Fix typo * Split long line * Add information to the documentation * Rename `LinkAsReadOnly` to `AlwaysOverwrite_LinkAsReadOnly` * Update docs Co-authored-by: Metadorius <[email protected]> * Improve text Co-authored-by: SadPencil <[email protected]> * Rename LinkAsReadOnly for built-in config * Code style changes * Rename FileOperationOptions to the singular form * Remove unnecessary usings * options -> option * Explicitly make FileOperationOption.AlwaysOverwrite as default * Set readonly property for linked translation files in target path * Update docs to recommend editing source files for translation * Update Translation.md --------- Co-authored-by: SadPencil <[email protected]> Co-authored-by: Metadorius <[email protected]> Co-authored-by: SadPencil <[email protected]>
- Loading branch information
1 parent
248a551
commit b47495f
Showing
35 changed files
with
803 additions
and
45 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.IO; | ||
using System.Linq; | ||
using System.Runtime.InteropServices; | ||
using System.Runtime.Versioning; | ||
using System.Text; | ||
using System.Threading.Tasks; | ||
|
||
using ClientCore.Extensions; | ||
|
||
using Rampastring.Tools; | ||
|
||
namespace ClientCore | ||
{ | ||
public class FileHelper | ||
{ | ||
|
||
/// <summary> | ||
/// Establishes a hard link between an existing file and a new file. This function is only supported on the NTFS file system, and only for files, not directories. | ||
/// <br/> | ||
/// https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-createhardlinkw | ||
/// </summary> | ||
/// <param name="lpFileName">The name of the new file.</param> | ||
/// <param name="lpExistingFileName">The name of the existing file.</param> | ||
/// <param name="lpSecurityAttributes">Reserved; must be NULL.</param> | ||
/// <returns>If the function succeeds, the return value is nonzero. If the function fails, the return value is zero (0).</returns> | ||
[DllImport("Kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode, EntryPoint = "CreateHardLinkW")] | ||
[DefaultDllImportSearchPaths(DllImportSearchPath.System32)] | ||
[SupportedOSPlatform("windows")] | ||
private static extern bool CreateHardLink(string lpFileName, string lpExistingFileName, IntPtr lpSecurityAttributes); | ||
|
||
/// <summary> | ||
/// The link function makes a new link to the existing file named by oldname, under the new name newname. | ||
/// <br/> | ||
/// https://www.gnu.org/software/libc/manual/html_node/Hard-Links.html | ||
/// <param name="oldname"></param> | ||
/// <param name="newname"></param> | ||
/// <returns>This function returns a value of 0 if it is successful and -1 on failure.</returns> | ||
[DllImport("libc", EntryPoint = "link", SetLastError = true)] | ||
[SupportedOSPlatform("linux")] | ||
[SupportedOSPlatform("osx")] | ||
private static extern int link([MarshalAs(UnmanagedType.LPUTF8Str)] string oldname, [MarshalAs(UnmanagedType.LPUTF8Str)] string newname); | ||
|
||
/// <summary> | ||
/// Creates hard link to the source file or copy that file, if got an error. | ||
/// </summary> | ||
/// <param name="source"></param> | ||
/// <param name="destination"></param> | ||
/// <param name="fallback"></param> | ||
/// <exception cref="IOException"></exception> | ||
/// <exception cref="PlatformNotSupportedException"></exception> | ||
public static void CreateHardLinkFromSource(string source, string destination, bool fallback = true) | ||
{ | ||
if (fallback) | ||
{ | ||
try | ||
{ | ||
CreateHardLinkFromSource(source, destination, fallback: false); | ||
} | ||
catch (Exception ex) | ||
{ | ||
Logger.Log($"Failed to create hard link at {destination}. Fallback to copy. {ex.Message}"); | ||
File.Copy(source, destination, true); | ||
} | ||
|
||
return; | ||
} | ||
|
||
if (File.Exists(destination)) | ||
{ | ||
FileInfo destinationFile = new(destination); | ||
destinationFile.IsReadOnly = false; | ||
destinationFile.Delete(); | ||
} | ||
|
||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) | ||
{ | ||
if (!CreateHardLink(destination, source, IntPtr.Zero)) | ||
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); | ||
} | ||
else if (RuntimeInformation.IsOSPlatform(OSPlatform.Linux) || RuntimeInformation.IsOSPlatform(OSPlatform.OSX)) | ||
{ | ||
if (link(source, destination) != 0) | ||
throw new IOException(string.Format("Unable to create hard link at {0} with the following error code: {1}" | ||
.L10N("Client:DTAConfig:CreateHardLinkFailed"), destination, Marshal.GetLastWin32Error())); | ||
} | ||
else | ||
{ | ||
throw new PlatformNotSupportedException(); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
DXMainClient/Resources/DTA/Compatibility/Configs/aqrit.cfg
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
;;; www.bitpatch.com ;;; | ||
|
||
RealDDrawPath = AUTO | ||
BltMirror = 0 | ||
BltNoTearing = 0 | ||
ColorFix = 0 | ||
DisableHighDpiScaling = 0 | ||
FakeVsync = 0 | ||
FakeVsyncInterval = 0 | ||
ForceBltNoTearing = 0 | ||
ForceDirectDrawEmulation = 1 | ||
NoVideoMemory = 0 | ||
SingleProcAffinity = 0 | ||
ShowFPS = 0 | ||
|
||
|
||
|
||
|
||
|
||
|
Oops, something went wrong.