Add result ranges and convert savedata results to external results

This commit is contained in:
Alex Barney 2019-06-30 23:49:52 -05:00
parent bbf92766c0
commit 69658ae08e
14 changed files with 278 additions and 53 deletions

View file

@ -1,7 +1,5 @@
using System.Collections.Generic; using System.Collections.Generic;
using static LibHac.Results;
namespace LibHac.Fs.Accessors namespace LibHac.Fs.Accessors
{ {
public class MountTable public class MountTable
@ -23,7 +21,7 @@ namespace LibHac.Fs.Accessors
Table.Add(mountName, fileSystem); Table.Add(mountName, fileSystem);
return ResultSuccess; return Result.Success;
} }
} }
@ -36,7 +34,7 @@ namespace LibHac.Fs.Accessors
return ResultFs.MountNameNotFound; return ResultFs.MountNameNotFound;
} }
return ResultSuccess; return Result.Success;
} }
} }
@ -52,7 +50,7 @@ namespace LibHac.Fs.Accessors
Table.Remove(name); Table.Remove(name);
fsAccessor.Close(); fsAccessor.Close();
return ResultSuccess; return Result.Success;
} }
} }
} }

View file

@ -3,8 +3,6 @@ using System.Collections.Generic;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using LibHac.Fs.Accessors; using LibHac.Fs.Accessors;
using static LibHac.Results;
namespace LibHac.Fs namespace LibHac.Fs
{ {
public class FileSystemManager public class FileSystemManager
@ -508,7 +506,7 @@ namespace LibHac.Fs
result = MountTable.Find(mountName.ToString(), out fileSystem); result = MountTable.Find(mountName.ToString(), out fileSystem);
if (result.IsFailure()) return result; if (result.IsFailure()) return result;
return ResultSuccess; return Result.Success;
} }
internal Result GetMountName(ReadOnlySpan<char> path, out ReadOnlySpan<char> mountName, out ReadOnlySpan<char> subPath) internal Result GetMountName(ReadOnlySpan<char> path, out ReadOnlySpan<char> mountName, out ReadOnlySpan<char> subPath)
@ -544,7 +542,7 @@ namespace LibHac.Fs
subPath = default; subPath = default;
} }
return ResultSuccess; return Result.Success;
} }
internal bool IsEnabledAccessLog() internal bool IsEnabledAccessLog()

View file

@ -2,8 +2,6 @@
using System.Diagnostics; using System.Diagnostics;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using static LibHac.Results;
#if !NETFRAMEWORK #if !NETFRAMEWORK
using System.IO.Enumeration; using System.IO.Enumeration;
#endif #endif
@ -376,7 +374,7 @@ namespace LibHac.Fs
if (path[i] == MountSeparator) if (path[i] == MountSeparator)
{ {
mountName = path.Substring(0, i); mountName = path.Substring(0, i);
return ResultSuccess; return Result.Success;
} }
} }

View file

@ -5,9 +5,15 @@
public const int ModuleFs = 2; public const int ModuleFs = 2;
public static Result PathNotFound => new Result(ModuleFs, 1); public static Result PathNotFound => new Result(ModuleFs, 1);
public static Result PathAlreadyExists => new Result(ModuleFs, 2);
public static Result TargetLocked => new Result(ModuleFs, 7);
public static Result DirectoryNotEmpty => new Result(ModuleFs, 8);
public static Result InsufficientFreeSpace => new Result(ModuleFs, 30);
public static Result MountNameAlreadyExists => new Result(ModuleFs, 60); public static Result MountNameAlreadyExists => new Result(ModuleFs, 60);
public static Result NotImplemented => new Result(ModuleFs, 3001); public static Result NotImplemented => new Result(ModuleFs, 3001);
public static Result Result3002 => new Result(ModuleFs, 3002);
public static Result SaveDataPathAlreadyExists => new Result(ModuleFs, 3003);
public static Result ValueOutOfRange => new Result(ModuleFs, 3005); public static Result ValueOutOfRange => new Result(ModuleFs, 3005);
public static Result AesXtsFileFileStorageAllocationError => new Result(ModuleFs, 3312); public static Result AesXtsFileFileStorageAllocationError => new Result(ModuleFs, 3312);
@ -18,15 +24,33 @@
public static Result InvalidIndirectStorageSource => new Result(ModuleFs, 4023); public static Result InvalidIndirectStorageSource => new Result(ModuleFs, 4023);
public static Result Result4302 => new Result(ModuleFs, 4302);
public static Result InvalidSaveDataHeader => new Result(ModuleFs, 4315); public static Result InvalidSaveDataHeader => new Result(ModuleFs, 4315);
public static Result Result4362 => new Result(ModuleFs, 4362);
public static Result Result4363 => new Result(ModuleFs, 4363);
public static Result InvalidHashInSaveIvfc => new Result(ModuleFs, 4364);
public static Result SaveIvfcHashIsEmpty => new Result(ModuleFs, 4372);
public static Result InvalidHashInSaveIvfcTopLayer => new Result(ModuleFs, 4373);
public static Result Result4402 => new Result(ModuleFs, 4402);
public static Result Result4427 => new Result(ModuleFs, 4427);
public static Result SaveDataAllocationTableCorrupted => new Result(ModuleFs, 4462);
public static Result SaveDataFileTableCorrupted => new Result(ModuleFs, 4463);
public static Result AllocationTableIteratedRangeEntry => new Result(ModuleFs, 4464);
public static Result Result4602 => new Result(ModuleFs, 4602);
public static Result Result4603 => new Result(ModuleFs, 4603);
public static Result InvalidHashInIvfc => new Result(ModuleFs, 4604); public static Result InvalidHashInIvfc => new Result(ModuleFs, 4604);
public static Result IvfcHashIsEmpty => new Result(ModuleFs, 4612); public static Result IvfcHashIsEmpty => new Result(ModuleFs, 4612);
public static Result InvalidHashInIvfcTopLayer => new Result(ModuleFs, 4613); public static Result InvalidHashInIvfcTopLayer => new Result(ModuleFs, 4613);
public static Result InvalidPartitionFileSystemMagic => new Result(ModuleFs, 4644); public static Result InvalidPartitionFileSystemMagic => new Result(ModuleFs, 4644);
public static Result InvalidHashedPartitionFileSystemMagic => new Result(ModuleFs, 4645); public static Result InvalidHashedPartitionFileSystemMagic => new Result(ModuleFs, 4645);
public static Result Result4662 => new Result(ModuleFs, 4662);
public static Result SaveDataAllocationTableCorruptedInternal => new Result(ModuleFs, 4722);
public static Result SaveDataFileTableCorruptedInternal => new Result(ModuleFs, 4723);
public static Result AllocationTableIteratedRangeEntryInternal => new Result(ModuleFs, 4724);
public static Result AesXtsFileHeaderTooShort => new Result(ModuleFs, 4742); public static Result AesXtsFileHeaderTooShort => new Result(ModuleFs, 4742);
public static Result AesXtsFileHeaderInvalidKeys => new Result(ModuleFs, 4743); public static Result AesXtsFileHeaderInvalidKeys => new Result(ModuleFs, 4743);
public static Result AesXtsFileHeaderInvalidMagic => new Result(ModuleFs, 4744); public static Result AesXtsFileHeaderInvalidMagic => new Result(ModuleFs, 4744);
@ -35,7 +59,18 @@
public static Result AesXtsFileHeaderInvalidKeysInRenameFile => new Result(ModuleFs, 4747); public static Result AesXtsFileHeaderInvalidKeysInRenameFile => new Result(ModuleFs, 4747);
public static Result AesXtsFileHeaderInvalidKeysInSetSize => new Result(ModuleFs, 4748); public static Result AesXtsFileHeaderInvalidKeysInSetSize => new Result(ModuleFs, 4748);
public static Result InvalidInput => new Result(ModuleFs, 6001); public static Result Result4812 => new Result(ModuleFs, 4812);
public static Result PreconditionViolation => new Result(ModuleFs, 6000);
public static Result InvalidArgument => new Result(ModuleFs, 6001);
public static Result InvalidPath => new Result(ModuleFs, 6002);
public static Result TooLongPath => new Result(ModuleFs, 6003);
public static Result InvalidCharacter => new Result(ModuleFs, 6004);
public static Result InvalidPathFormat => new Result(ModuleFs, 6005);
public static Result DirectoryUnobtainable => new Result(ModuleFs, 6006);
public static Result NotNormalized => new Result(ModuleFs, 6007);
public static Result PathNotFoundInSaveDataFileTable => new Result(ModuleFs, 6033);
public static Result DifferentDestFileSystem => new Result(ModuleFs, 6034); public static Result DifferentDestFileSystem => new Result(ModuleFs, 6034);
public static Result InvalidOffset => new Result(ModuleFs, 6061); public static Result InvalidOffset => new Result(ModuleFs, 6061);
public static Result InvalidSize => new Result(ModuleFs, 6062); public static Result InvalidSize => new Result(ModuleFs, 6062);
@ -60,6 +95,7 @@
public static Result UnsupportedOperationModifyPartitionFileSystem => new Result(ModuleFs, 6374); public static Result UnsupportedOperationModifyPartitionFileSystem => new Result(ModuleFs, 6374);
public static Result UnsupportedOperationInPartitionFileSetSize => new Result(ModuleFs, 6376); public static Result UnsupportedOperationInPartitionFileSetSize => new Result(ModuleFs, 6376);
public static Result PermissionDenied => new Result(ModuleFs, 6400);
public static Result WriteStateUnflushed => new Result(ModuleFs, 6454); public static Result WriteStateUnflushed => new Result(ModuleFs, 6454);
public static Result WritableFileOpen => new Result(ModuleFs, 6457); public static Result WritableFileOpen => new Result(ModuleFs, 6457);

View file

@ -0,0 +1,21 @@
namespace LibHac.Fs
{
public static class ResultRangeFs
{
public static ResultRange DataCorrupted => new ResultRange(ResultFs.ModuleFs, 4000, 4999);
public static ResultRange RomCorrupted => new ResultRange(ResultFs.ModuleFs, 4001, 4299);
public static ResultRange SaveDataCorrupted => new ResultRange(ResultFs.ModuleFs, 4301, 4499);
public static ResultRange NcaCorrupted => new ResultRange(ResultFs.ModuleFs, 4501, 4599);
public static ResultRange IvfcStorageCorrupted => new ResultRange(ResultFs.ModuleFs, 4601, 4639);
public static ResultRange PartitionFsCorrupted => new ResultRange(ResultFs.ModuleFs, 4641, 4659);
public static ResultRange BuiltInStorageCorrupted => new ResultRange(ResultFs.ModuleFs, 4661, 4679);
public static ResultRange FatFsCorrupted => new ResultRange(ResultFs.ModuleFs, 4681, 4699);
public static ResultRange HostFsCorrupted => new ResultRange(ResultFs.ModuleFs, 4701, 4719);
public static ResultRange FileTableCorrupted => new ResultRange(ResultFs.ModuleFs, 4721, 4739);
public static ResultRange Range4811To4819 => new ResultRange(ResultFs.ModuleFs, 4811, 4819);
public static ResultRange UnexpectedFailure => new ResultRange(ResultFs.ModuleFs, 5000, 5999);
public static ResultRange EntryNotFound => new ResultRange(ResultFs.ModuleFs, 6600, 6699);
}
}

View file

@ -64,7 +64,7 @@ namespace LibHac.Fs.RomFs
if (mode != OpenMode.Read) if (mode != OpenMode.Read)
{ {
ThrowHelper.ThrowResult(ResultFs.InvalidInput, "RomFs files must be opened read-only."); ThrowHelper.ThrowResult(ResultFs.InvalidArgument, "RomFs files must be opened read-only.");
} }
return new RomFsFile(BaseStorage, Header.DataOffset + info.Offset, info.Length); return new RomFsFile(BaseStorage, Header.DataOffset + info.Offset, info.Length);

View file

@ -35,6 +35,11 @@ namespace LibHac.Fs.Save
if (entries[0].IsSingleBlockSegment()) if (entries[0].IsSingleBlockSegment())
{ {
length = 1; length = 1;
if (entries[0].IsRangeEntry())
{
ThrowHelper.ThrowResult(ResultFs.AllocationTableIteratedRangeEntryInternal);
}
} }
else else
{ {
@ -482,6 +487,11 @@ namespace LibHac.Fs.Save
Prev = int.MinValue; Prev = int.MinValue;
} }
public bool IsRangeEntry()
{
return Prev != int.MinValue && Prev < 0;
}
public void MakeRangeEntry() public void MakeRangeEntry()
{ {
Prev |= unchecked((int)0x80000000); Prev |= unchecked((int)0x80000000);

View file

@ -0,0 +1,127 @@
namespace LibHac.Fs.Save
{
internal static class SaveResults
{
public static Result ConvertToExternalResult(Result result)
{
int description = result.Description;
if (result == Result.Success)
{
return Result.Success;
}
if (result.Module != ResultFs.ModuleFs)
{
return result;
}
if (result == ResultFs.Result3002)
{
return ResultFs.Result4302;
}
if (ResultRangeFs.IvfcStorageCorrupted.Contains(result))
{
if (result == ResultFs.Result4602)
{
return ResultFs.Result4362;
}
if (result == ResultFs.Result4603)
{
return ResultFs.Result4363;
}
if (result == ResultFs.InvalidHashInIvfc)
{
return ResultFs.InvalidHashInSaveIvfc;
}
if (result == ResultFs.IvfcHashIsEmpty)
{
return ResultFs.SaveIvfcHashIsEmpty;
}
if (result == ResultFs.InvalidHashInIvfcTopLayer)
{
return ResultFs.InvalidHashInSaveIvfcTopLayer;
}
return result;
}
if (ResultRangeFs.BuiltInStorageCorrupted.Contains(result))
{
if (result == ResultFs.Result4662)
{
return ResultFs.Result4402;
}
return result;
}
if (ResultRangeFs.HostFsCorrupted.Contains(result))
{
if (description > 4701 && description < 4706)
{
return new Result(ResultFs.ModuleFs, description - 260);
}
return result;
}
if (ResultRangeFs.Range4811To4819.Contains(result))
{
if (result == ResultFs.Result4812)
{
return ResultFs.Result4427;
}
return result;
}
if (ResultRangeFs.FileTableCorrupted.Contains(result))
{
if (description > 4721 && description < 4729)
{
return new Result(ResultFs.ModuleFs, (description - 260));
}
return result;
}
if (ResultRangeFs.FatFsCorrupted.Contains(result))
{
return result;
}
if (ResultRangeFs.EntryNotFound.Contains(result))
{
return ResultFs.PathNotFound;
}
if (result == ResultFs.SaveDataPathAlreadyExists)
{
return ResultFs.PathAlreadyExists;
}
if (result == ResultFs.PathNotFoundInSaveDataFileTable)
{
return ResultFs.PathNotFound;
}
if (result == ResultFs.InvalidOffset)
{
return ResultFs.ValueOutOfRange;
}
if (result == ResultFs.AllocationTableInsufficientFreeBlocks)
{
return ResultFs.InsufficientFreeSpace;
}
return result;
}
}
}

View file

@ -1,9 +1,6 @@
using System; using System;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using static LibHac.Results;
using static LibHac.Kvdb.ResultsKvdb;
namespace LibHac.Kvdb namespace LibHac.Kvdb
{ {
public ref struct ImkvdbReader public ref struct ImkvdbReader
@ -21,19 +18,19 @@ namespace LibHac.Kvdb
{ {
entryCount = default; entryCount = default;
if (_position + Unsafe.SizeOf<ImkvdbHeader>() > _data.Length) return ResultKvdbInvalidKeyValue; if (_position + Unsafe.SizeOf<ImkvdbHeader>() > _data.Length) return ResultKvdb.InvalidKeyValue;
ref ImkvdbHeader header = ref Unsafe.As<byte, ImkvdbHeader>(ref Unsafe.AsRef(_data[_position])); ref ImkvdbHeader header = ref Unsafe.As<byte, ImkvdbHeader>(ref Unsafe.AsRef(_data[_position]));
if (header.Magic != ImkvdbHeader.ExpectedMagic) if (header.Magic != ImkvdbHeader.ExpectedMagic)
{ {
return ResultKvdbInvalidKeyValue; return ResultKvdb.InvalidKeyValue;
} }
entryCount = header.EntryCount; entryCount = header.EntryCount;
_position += Unsafe.SizeOf<ImkvdbHeader>(); _position += Unsafe.SizeOf<ImkvdbHeader>();
return ResultSuccess; return Result.Success;
} }
public Result GetEntrySize(out int keySize, out int valueSize) public Result GetEntrySize(out int keySize, out int valueSize)
@ -41,19 +38,19 @@ namespace LibHac.Kvdb
keySize = default; keySize = default;
valueSize = default; valueSize = default;
if (_position + Unsafe.SizeOf<ImkvdbHeader>() > _data.Length) return ResultKvdbInvalidKeyValue; if (_position + Unsafe.SizeOf<ImkvdbHeader>() > _data.Length) return ResultKvdb.InvalidKeyValue;
ref ImkvdbEntryHeader header = ref Unsafe.As<byte, ImkvdbEntryHeader>(ref Unsafe.AsRef(_data[_position])); ref ImkvdbEntryHeader header = ref Unsafe.As<byte, ImkvdbEntryHeader>(ref Unsafe.AsRef(_data[_position]));
if (header.Magic != ImkvdbEntryHeader.ExpectedMagic) if (header.Magic != ImkvdbEntryHeader.ExpectedMagic)
{ {
return ResultKvdbInvalidKeyValue; return ResultKvdb.InvalidKeyValue;
} }
keySize = header.KeySize; keySize = header.KeySize;
valueSize = header.ValueSize; valueSize = header.ValueSize;
return ResultSuccess; return Result.Success;
} }
public Result ReadEntry(out ReadOnlySpan<byte> key, out ReadOnlySpan<byte> value) public Result ReadEntry(out ReadOnlySpan<byte> key, out ReadOnlySpan<byte> value)
@ -66,14 +63,14 @@ namespace LibHac.Kvdb
_position += Unsafe.SizeOf<ImkvdbEntryHeader>(); _position += Unsafe.SizeOf<ImkvdbEntryHeader>();
if (_position + keySize + valueSize > _data.Length) return ResultKvdbInvalidKeyValue; if (_position + keySize + valueSize > _data.Length) return ResultKvdb.InvalidKeyValue;
key = _data.Slice(_position, keySize); key = _data.Slice(_position, keySize);
value = _data.Slice(_position + keySize, valueSize); value = _data.Slice(_position + keySize, valueSize);
_position += keySize + valueSize; _position += keySize + valueSize;
return ResultSuccess; return Result.Success;
} }
} }
} }

View file

@ -3,9 +3,6 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Runtime.CompilerServices; using System.Runtime.CompilerServices;
using static LibHac.Results;
using static LibHac.Kvdb.ResultsKvdb;
namespace LibHac.Kvdb namespace LibHac.Kvdb
{ {
// Todo: Save and load from file // Todo: Save and load from file
@ -21,10 +18,10 @@ namespace LibHac.Kvdb
{ {
if (!KvDict.TryGetValue(key, out value)) if (!KvDict.TryGetValue(key, out value))
{ {
return ResultKvdbKeyNotFound; return ResultKvdb.KeyNotFound;
} }
return ResultSuccess; return Result.Success;
} }
public Result Set(TKey key, TValue value) public Result Set(TKey key, TValue value)
@ -33,7 +30,7 @@ namespace LibHac.Kvdb
KvDict[key] = value; KvDict[key] = value;
return ResultSuccess; return Result.Success;
} }
public Result ReadDatabaseFromBuffer(ReadOnlySpan<byte> data) public Result ReadDatabaseFromBuffer(ReadOnlySpan<byte> data)
@ -59,7 +56,7 @@ namespace LibHac.Kvdb
KvDict.Add(key, value); KvDict.Add(key, value);
} }
return ResultSuccess; return Result.Success;
} }
public Result WriteDatabaseToBuffer(Span<byte> output) public Result WriteDatabaseToBuffer(Span<byte> output)
@ -73,7 +70,7 @@ namespace LibHac.Kvdb
writer.WriteEntry(entry.Key, entry.Value); writer.WriteEntry(entry.Key, entry.Value);
} }
return ResultSuccess; return Result.Success;
} }
public int GetExportedSize() public int GetExportedSize()

View file

@ -0,0 +1,13 @@
namespace LibHac.Kvdb
{
public static class ResultKvdb
{
public const int ModuleKvdb = 20;
public static Result TooLargeKey => new Result(ModuleKvdb, 1);
public static Result KeyNotFound => new Result(ModuleKvdb, 2);
public static Result AllocationFailed => new Result(ModuleKvdb, 4);
public static Result InvalidKeyValue => new Result(ModuleKvdb, 5);
public static Result BufferInsufficient => new Result(ModuleKvdb, 6);
}
}

View file

@ -1,13 +0,0 @@
namespace LibHac.Kvdb
{
public static class ResultsKvdb
{
public const int ModuleKvdb = 20;
public static Result ResultKvdbTooLargeKey => new Result(ModuleKvdb, 1);
public static Result ResultKvdbKeyNotFound => new Result(ModuleKvdb, 2);
public static Result ResultKvdbAllocationFailed => new Result(ModuleKvdb, 4);
public static Result ResultKvdbInvalidKeyValue => new Result(ModuleKvdb, 5);
public static Result ResultKvdbBufferInsufficient => new Result(ModuleKvdb, 6);
}
}

View file

@ -3,7 +3,7 @@
namespace LibHac namespace LibHac
{ {
[Serializable] [Serializable]
public struct Result public struct Result : IEquatable<Result>
{ {
public readonly int Value; public readonly int Value;
@ -31,10 +31,32 @@ namespace LibHac
ThrowHelper.ThrowResult(this); ThrowHelper.ThrowResult(this);
} }
} }
public override bool Equals(object obj)
{
return obj is Result result && Equals(result);
} }
public static class Results public bool Equals(Result other)
{ {
public static Result ResultSuccess => new Result(0); return Value == other.Value;
}
public override int GetHashCode()
{
return Value.GetHashCode();
}
public static bool operator ==(Result left, Result right)
{
return left.Equals(right);
}
public static bool operator !=(Result left, Result right)
{
return !left.Equals(right);
}
public static Result Success => new Result(0);
} }
} }

21
src/LibHac/ResultRange.cs Normal file
View file

@ -0,0 +1,21 @@
namespace LibHac
{
public struct ResultRange
{
private Result Start { get; }
private Result End { get; }
public ResultRange(int module, int descriptionStart, int descriptionEnd)
{
Start = new Result(module, descriptionStart);
End = new Result(module, descriptionEnd);
}
public bool Contains(Result result)
{
return result.Module == Start.Module &&
result.Description >= Start.Description &&
result.Description <= End.Description;
}
}
}