Skip to content

Commit

Permalink
fix: ignore case when making hard links
Browse files Browse the repository at this point in the history
  • Loading branch information
anna-is-cute committed Aug 18, 2024
1 parent 8e1dbd2 commit 30a6bc7
Show file tree
Hide file tree
Showing 3 changed files with 27 additions and 9 deletions.
9 changes: 5 additions & 4 deletions ConvertTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@
using Heliosphere.Util;
using Newtonsoft.Json;
using StrawberryShake;
using Windows.Win32;

namespace Heliosphere;

Expand Down Expand Up @@ -116,16 +115,18 @@ internal async Task Run() {
throw new SecurityException("path from mod was attempting to leave the files directory");
}

if (outputPath.Equals(existingPath, StringComparison.InvariantCultureIgnoreCase)) {
continue;
}

if (File.Exists(outputPath)) {
continue;
}

var parent = PathHelper.GetParent(outputPath);
Directory.CreateDirectory(parent);

if (!PInvoke.CreateHardLink(@$"\\?\{outputPath}", @$"\\?\{existingPath}")) {
throw new IOException($"failed to create hard link: {existingPath} -> {outputPath}");
}
FileHelper.CreateHardLink(existingPath, outputPath);
}

finished += 1;
Expand Down
7 changes: 2 additions & 5 deletions DownloadTask.cs
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
using Newtonsoft.Json.Linq;
using Penumbra.Api.Enums;
using StrawberryShake;
using Windows.Win32;
using ZstdSharp;

namespace Heliosphere;
Expand Down Expand Up @@ -714,7 +713,7 @@ private static async Task DuplicateFile(string filesDir, IEnumerable<string> out

async Task DuplicateInner(string dest) {
dest = Path.Join(filesDir, dest);
if (path == dest) {
if (path.Equals(dest, StringComparison.InvariantCultureIgnoreCase)) {
return;
}

Expand All @@ -729,9 +728,7 @@ async Task DuplicateInner(string dest) {
var parent = PathHelper.GetParent(dest);
Plugin.Resilience.Execute(() => Directory.CreateDirectory(parent));

if (!PInvoke.CreateHardLink(@$"\\?\{dest}", @$"\\?\{path}")) {
throw new IOException($"failed to create hard link {path} -> {dest}");
}
FileHelper.CreateHardLink(path, dest);
}
}

Expand Down
20 changes: 20 additions & 0 deletions Util/FileHelper.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Runtime.InteropServices;
using Heliosphere.Exceptions;
using Windows.Win32;

namespace Heliosphere.Util;

Expand Down Expand Up @@ -89,4 +91,22 @@ private static async Task<T> WrapAsync<T>(string path, Func<string, Task<T>> act
throw new AlreadyInUseException(io, path, procs);
}
}

internal static void CreateHardLink(string source, string destination) {
const string prefix = @"\\?\";

var prefixedSource = source.StartsWith(prefix)
? source
: prefix + source;
var prefixedDestination = destination.StartsWith(prefix)
? destination
: prefix + destination;

if (PInvoke.CreateHardLink(prefixedDestination, prefixedSource)) {
return;
}

var error = Marshal.GetLastWin32Error();
throw new IOException($"Failed to create hard link (0x{error:X}): {source} -> {destination}");
}
}

0 comments on commit 30a6bc7

Please sign in to comment.