mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
LocalFileSystem: Allow deleting read-only files and directories
This commit is contained in:
parent
6910049070
commit
2540f071ea
3 changed files with 82 additions and 3 deletions
|
@ -19,6 +19,7 @@ internal static class HResult
|
||||||
public const int ERROR_ALREADY_EXISTS = unchecked((int)0x800700B7);
|
public const int ERROR_ALREADY_EXISTS = unchecked((int)0x800700B7);
|
||||||
public const int ERROR_DIRECTORY = unchecked((int)0x8007010B);
|
public const int ERROR_DIRECTORY = unchecked((int)0x8007010B);
|
||||||
public const int ERROR_SPACES_NOT_ENOUGH_DRIVES = unchecked((int)0x80E7000B);
|
public const int ERROR_SPACES_NOT_ENOUGH_DRIVES = unchecked((int)0x80E7000B);
|
||||||
|
public const int COR_E_IO = unchecked((int)0x80131620);
|
||||||
|
|
||||||
public static Result HResultToHorizonResult(int hResult) => hResult switch
|
public static Result HResultToHorizonResult(int hResult) => hResult switch
|
||||||
{
|
{
|
||||||
|
@ -35,6 +36,7 @@ internal static class HResult
|
||||||
ERROR_ALREADY_EXISTS => ResultFs.PathAlreadyExists.Value,
|
ERROR_ALREADY_EXISTS => ResultFs.PathAlreadyExists.Value,
|
||||||
ERROR_DIRECTORY => ResultFs.PathNotFound.Value,
|
ERROR_DIRECTORY => ResultFs.PathNotFound.Value,
|
||||||
ERROR_SPACES_NOT_ENOUGH_DRIVES => ResultFs.UsableSpaceNotEnough.Value,
|
ERROR_SPACES_NOT_ENOUGH_DRIVES => ResultFs.UsableSpaceNotEnough.Value,
|
||||||
|
COR_E_IO => ResultFs.TargetLocked.Value,
|
||||||
_ => ResultFs.UnexpectedInLocalFileSystemE.Value
|
_ => ResultFs.UnexpectedInLocalFileSystemE.Value
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ namespace LibHac.FsSystem.Impl;
|
||||||
|
|
||||||
internal static class TargetLockedAvoidance
|
internal static class TargetLockedAvoidance
|
||||||
{
|
{
|
||||||
private const int RetryCount = 2;
|
private const int RetryCount = 25;
|
||||||
private const int SleepTimeMs = 2;
|
private const int SleepTimeMs = 2;
|
||||||
|
|
||||||
// Allow usage outside of a Horizon context by using standard .NET APIs
|
// Allow usage outside of a Horizon context by using standard .NET APIs
|
||||||
|
|
|
@ -651,10 +651,31 @@ public class LocalFileSystem : IAttributeFileSystem
|
||||||
if (!dir.Exists)
|
if (!dir.Exists)
|
||||||
return ResultFs.PathNotFound.Log();
|
return ResultFs.PathNotFound.Log();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
dir.Delete(recursive);
|
dir.Delete(recursive);
|
||||||
}
|
}
|
||||||
|
catch (Exception ex) when (ex.HResult is HResult.COR_E_IO or HResult.ERROR_ACCESS_DENIED)
|
||||||
|
{
|
||||||
|
if (recursive)
|
||||||
|
{
|
||||||
|
Result rc = DeleteDirectoryRecursivelyWithReadOnly(dir);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Try to delete read-only directories by first removing the read-only flag
|
||||||
|
if (dir.Attributes.HasFlag(FileAttributes.ReadOnly))
|
||||||
|
{
|
||||||
|
dir.Attributes &= ~FileAttributes.ReadOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
dir.Delete(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (Exception ex) when (ex.HResult < 0)
|
catch (Exception ex) when (ex.HResult < 0)
|
||||||
{
|
{
|
||||||
return HResult.HResultToHorizonResult(ex.HResult).Log();
|
return HResult.HResultToHorizonResult(ex.HResult).Log();
|
||||||
|
@ -668,10 +689,23 @@ public class LocalFileSystem : IAttributeFileSystem
|
||||||
if (!file.Exists)
|
if (!file.Exists)
|
||||||
return ResultFs.PathNotFound.Log();
|
return ResultFs.PathNotFound.Log();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
file.Delete();
|
file.Delete();
|
||||||
}
|
}
|
||||||
|
catch (UnauthorizedAccessException ex) when (ex.HResult == HResult.ERROR_ACCESS_DENIED)
|
||||||
|
{
|
||||||
|
// Try to delete read-only files by first removing the read-only flag.
|
||||||
|
if (file.Attributes.HasFlag(FileAttributes.ReadOnly))
|
||||||
|
{
|
||||||
|
file.Attributes &= ~FileAttributes.ReadOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.Delete();
|
||||||
|
}
|
||||||
|
}
|
||||||
catch (Exception ex) when (ex.HResult < 0)
|
catch (Exception ex) when (ex.HResult < 0)
|
||||||
{
|
{
|
||||||
return HResult.HResultToHorizonResult(ex.HResult).Log();
|
return HResult.HResultToHorizonResult(ex.HResult).Log();
|
||||||
|
@ -680,6 +714,49 @@ public class LocalFileSystem : IAttributeFileSystem
|
||||||
return EnsureDeleted(file);
|
return EnsureDeleted(file);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Result DeleteDirectoryRecursivelyWithReadOnly(DirectoryInfo rootDir)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (FileSystemInfo info in rootDir.EnumerateFileSystemInfos())
|
||||||
|
{
|
||||||
|
if (info is FileInfo file)
|
||||||
|
{
|
||||||
|
// Check each file for the read-only flag before deleting.
|
||||||
|
if (file.Attributes.HasFlag(FileAttributes.ReadOnly))
|
||||||
|
{
|
||||||
|
file.Attributes &= ~FileAttributes.ReadOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
file.Delete();
|
||||||
|
}
|
||||||
|
else if (info is DirectoryInfo dir)
|
||||||
|
{
|
||||||
|
Result rc = DeleteDirectoryRecursivelyWithReadOnly(dir);
|
||||||
|
if (rc.IsFailure()) return rc.Miss();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return ResultFs.UnexpectedInLocalFileSystemF.Log();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// The directory should be empty now. Remove any read-only flag and delete it.
|
||||||
|
if (rootDir.Attributes.HasFlag(FileAttributes.ReadOnly))
|
||||||
|
{
|
||||||
|
rootDir.Attributes &= ~FileAttributes.ReadOnly;
|
||||||
|
}
|
||||||
|
|
||||||
|
rootDir.Delete(true);
|
||||||
|
}
|
||||||
|
catch (Exception ex) when (ex.HResult < 0)
|
||||||
|
{
|
||||||
|
return HResult.HResultToHorizonResult(ex.HResult).Log();
|
||||||
|
}
|
||||||
|
|
||||||
|
return Result.Success;
|
||||||
|
}
|
||||||
|
|
||||||
private static Result CreateDirInternal(DirectoryInfo dir, NxFileAttributes attributes)
|
private static Result CreateDirInternal(DirectoryInfo dir, NxFileAttributes attributes)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
|
|
Loading…
Reference in a new issue