mirror of
https://github.com/k1tbyte/Wand-Enhancer.git
synced 2026-09-04 08:13:18 +00:00
feat(patch): report what is blocking a denied copy
An access-denied copy now names the destination's attributes, owner and the account running the patcher.
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security.AccessControl;
|
||||
using System.Security.Principal;
|
||||
using System.Text;
|
||||
|
||||
namespace AsarSharp.Utils
|
||||
@@ -162,16 +164,71 @@ namespace AsarSharp.Utils
|
||||
public static void CopyOver(string source, string destination)
|
||||
{
|
||||
ClearAttributes(destination);
|
||||
File.Copy(source, destination, true);
|
||||
|
||||
try
|
||||
{
|
||||
File.Copy(source, destination, true);
|
||||
}
|
||||
catch (UnauthorizedAccessException e)
|
||||
{
|
||||
throw new UnauthorizedAccessException($"{e.Message} {DescribeDenial(destination)}", e);
|
||||
}
|
||||
|
||||
ClearAttributes(destination);
|
||||
}
|
||||
|
||||
/// <summary>Resets a file to Normal: ReadOnly, Hidden and System all block an overwrite.</summary>
|
||||
/// <summary>
|
||||
/// "Access to the path is denied" names none of the half-dozen things that cause it, and
|
||||
/// the state is gone by the time anyone reads the report. Attributes were already cleared
|
||||
/// above, which rules the most common cause out before the message is even written.
|
||||
/// </summary>
|
||||
private static string DescribeDenial(string destination)
|
||||
{
|
||||
if (Directory.Exists(destination))
|
||||
{
|
||||
return "The destination is a directory, not a file.";
|
||||
}
|
||||
|
||||
if (!File.Exists(destination))
|
||||
{
|
||||
return "The destination does not exist, so the containing folder is refusing new files.";
|
||||
}
|
||||
|
||||
return $"Attributes {File.GetAttributes(destination)}, owner {DescribeOwner(destination)}, " +
|
||||
$"running as {Environment.UserName}. A read-only flag, antivirus, folder " +
|
||||
"permissions or a delete still pending on the file are the usual causes.";
|
||||
}
|
||||
|
||||
private static string DescribeOwner(string path)
|
||||
{
|
||||
try
|
||||
{
|
||||
return File.GetAccessControl(path).GetOwner(typeof(NTAccount)).Value;
|
||||
}
|
||||
catch (Exception e) when (e is IdentityNotMappedException || e is UnauthorizedAccessException ||
|
||||
e is InvalidOperationException || e is PrivilegeNotHeldException ||
|
||||
e is PlatformNotSupportedException)
|
||||
{
|
||||
return "unreadable";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Resets a file to Normal: ReadOnly, Hidden and System all block an overwrite. Best
|
||||
/// effort - a file that denies even this reports it properly through the write that follows.
|
||||
/// </summary>
|
||||
public static void ClearAttributes(string path)
|
||||
{
|
||||
if (File.Exists(path))
|
||||
try
|
||||
{
|
||||
File.SetAttributes(path, FileAttributes.Normal);
|
||||
if (File.Exists(path))
|
||||
{
|
||||
File.SetAttributes(path, FileAttributes.Normal);
|
||||
}
|
||||
}
|
||||
catch (Exception e) when (e is UnauthorizedAccessException || e is IOException)
|
||||
{
|
||||
// Swallowed so the caller's own failure is the one that surfaces.
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user