Finish OpenFileSystemWithId enough to work with most content

This commit is contained in:
Alex Barney 2020-03-10 15:07:06 -07:00
parent 281fc8aac3
commit 036e048208
9 changed files with 219 additions and 18 deletions

View file

@ -81,6 +81,8 @@ Module,DescriptionStart,DescriptionEnd,Name,Summary
2,4464,,AllocationTableIteratedRangeEntry,
2,4501,4599,NcaCorrupted,
2,4512,,InvalidNcaFsType,
2,4527,,InvalidNcaProgramId,
2,4601,4639,IntegrityVerificationStorageCorrupted,
2,4602,,InvalidIvfcMagic,

1 Module,DescriptionStart,DescriptionEnd,Name,Summary
81 2,4645,,InvalidHashedPartitionFileSystemMagic, 2,4643,,InvalidPartitionFileSystemHash,
82 2,4646,,InvalidPartitionFileSystemEntryNameOffset, 2,4644,,InvalidPartitionFileSystemMagic,
83 2,4661,4679,BuiltInStorageCorrupted, 2,4645,,InvalidHashedPartitionFileSystemMagic,
84 2,4646,,InvalidPartitionFileSystemEntryNameOffset,
85 2,4661,4679,BuiltInStorageCorrupted,
86 2,4662,,InvalidGptPartitionSignature,
87 2,4681,4699,FatFileSystemCorrupted,
88 2,4701,4719,HostFileSystemCorrupted,

View file

@ -6,10 +6,10 @@ namespace LibHac.Fs
{
public class FileStorage2 : StorageBase
{
private const long InvalidSize = -1;
protected const long InvalidSize = -1;
private IFile BaseFile { get; set; }
private long FileSize { get; set; }
protected long FileSize { get; set; }
public FileStorage2(IFile baseFile)
{

View file

@ -9,7 +9,10 @@ namespace LibHac.Fs
private IFileSystem BaseFileSystem { get; set; }
private IFile BaseFile { get; set; }
private FileStorageBasedFileSystem() { }
private FileStorageBasedFileSystem()
{
FileSize = InvalidSize;
}
public static Result CreateNew(out FileStorageBasedFileSystem created, IFileSystem baseFileSystem, U8Span path,
OpenMode mode)

View file

@ -171,6 +171,10 @@ namespace LibHac.Fs
/// <summary>Error code: 2002-4501; Range: 4501-4599; Inner value: 0x232a02</summary>
public static Result.Base NcaCorrupted { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 4501, 4599); }
/// <summary>Error code: 2002-4512; Inner value: 0x234002</summary>
public static Result.Base InvalidNcaFsType => new Result.Base(ModuleFs, 4512);
/// <summary>Error code: 2002-4527; Inner value: 0x235e02</summary>
public static Result.Base InvalidNcaProgramId => new Result.Base(ModuleFs, 4527);
/// <summary>Error code: 2002-4601; Range: 4601-4639; Inner value: 0x23f202</summary>
public static Result.Base IntegrityVerificationStorageCorrupted { [MethodImpl(MethodImplOptions.AggressiveInlining)] get => new Result.Base(ModuleFs, 4601, 4639); }

View file

@ -1,13 +1,15 @@
using System;
using LibHac.Fs;
using LibHac.Fs;
using LibHac.FsSystem.RomFs;
namespace LibHac.FsService.Creators
{
public class RomFileSystemCreator : IRomFileSystemCreator
{
// todo: Implement properly
public Result Create(out IFileSystem fileSystem, IStorage romFsStorage)
{
throw new NotImplementedException();
fileSystem = new RomFsFileSystem(romFsStorage);
return Result.Success;
}
}
}

View file

@ -1,14 +1,46 @@
using System;
using LibHac.Fs;
using LibHac.FsSystem;
using LibHac.FsSystem.Detail;
using LibHac.FsSystem.NcaUtils;
namespace LibHac.FsService.Creators
{
public class StorageOnNcaCreator : IStorageOnNcaCreator
{
private bool IsEnabledProgramVerification { get; set; }
private Keyset Keyset { get; }
public StorageOnNcaCreator(Keyset keyset)
{
Keyset = keyset;
}
// todo: Implement NcaReader and other Nca classes
public Result Create(out IStorage storage, out NcaFsHeader fsHeader, Nca nca, int fsIndex, bool isCodeFs)
{
throw new NotImplementedException();
storage = default;
fsHeader = default;
Result rc = OpenStorage(out IStorage storageTemp, nca, fsIndex);
if (rc.IsFailure()) return rc;
if (isCodeFs)
{
using (var codeFs = new PartitionFileSystemCore<StandardEntry>())
{
rc = codeFs.Initialize(storageTemp);
if (rc.IsFailure()) return rc;
rc = VerifyAcidSignature(codeFs, nca);
if (rc.IsFailure()) return rc;
}
}
storage = storageTemp;
fsHeader = nca.Header.GetFsHeader(fsIndex);
return Result.Success;
}
public Result CreateWithPatch(out IStorage storage, out NcaFsHeader fsHeader, Nca baseNca, Nca patchNca, int fsIndex, bool isCodeFs)
@ -18,12 +50,25 @@ namespace LibHac.FsService.Creators
public Result OpenNca(out Nca nca, IStorage ncaStorage)
{
throw new NotImplementedException();
nca = new Nca(Keyset, ncaStorage);
return Result.Success;
}
public Result VerifyAcidSignature(IFileSystem codeFileSystem, Nca nca)
{
throw new NotImplementedException();
// todo
return Result.Success;
}
private Result OpenStorage(out IStorage storage, Nca nca, int fsIndex)
{
storage = default;
if (!nca.SectionExists(fsIndex))
return ResultFs.PartitionNotFound.Log();
storage = nca.OpenStorage(fsIndex, IntegrityCheckLevel.ErrorOnInvalid);
return Result.Success;
}
}
}

View file

@ -20,7 +20,7 @@ namespace LibHac.FsService
creators.RomFileSystemCreator = new RomFileSystemCreator();
creators.PartitionFileSystemCreator = new PartitionFileSystemCreator();
creators.StorageOnNcaCreator = new StorageOnNcaCreator();
creators.StorageOnNcaCreator = new StorageOnNcaCreator(keyset);
creators.TargetManagerFileSystemCreator = new TargetManagerFileSystemCreator();
creators.SubDirectoryFileSystemCreator = new SubDirectoryFileSystemCreator();
creators.SaveDataFileSystemCreator = new SaveDataFileSystemCreator(keyset);

View file

@ -40,11 +40,22 @@ namespace LibHac.FsService
bool canMountSystemDataPrivate = false;
Result rc = PathTools.Normalize(out U8Span normalizedPath, path);
if (rc.IsFailure()) return rc;
var normalizer = new PathNormalizer(path, GetPathNormalizerOptions(path));
if (normalizer.Result.IsFailure()) return normalizer.Result;
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
return FsProxyCore.OpenFileSystem(out fileSystem, normalizedPath, type, canMountSystemDataPrivate, titleId);
return FsProxyCore.OpenFileSystem(out fileSystem, normalizer.Path, type, canMountSystemDataPrivate, titleId);
}
private PathNormalizer.Option GetPathNormalizerOptions(U8Span path)
{
int hostMountLength = StringUtils.GetLength(CommonMountNames.HostRootFileSystemMountName,
PathTools.MountNameLengthMax);
bool isHostPath = StringUtils.Compare(path, CommonMountNames.HostRootFileSystemMountName, hostMountLength) == 0;
PathNormalizer.Option hostOption = isHostPath ? PathNormalizer.Option.PreserveUnc : PathNormalizer.Option.None;
return PathNormalizer.Option.HasMountName | PathNormalizer.Option.PreserveTailSeparator | hostOption;
}
public Result OpenFileSystemWithPatch(out IFileSystem fileSystem, TitleId titleId, FileSystemProxyType type)

View file

@ -1,4 +1,5 @@
using System;
using System.Runtime.CompilerServices;
using LibHac.Common;
using LibHac.Fs;
using LibHac.Fs.Shim;
@ -96,9 +97,19 @@ namespace LibHac.FsService
rc = TryOpenNca(ref path2, out Nca nca, baseFileSystem, openTitleId);
if (rc.IsFailure()) return rc;
rc = OpenNcaStorage(out IStorage ncaSectionStorage, nca, out NcaFormatType fsType, type,
mountNameInfo.IsGameCard, canMountSystemDataPrivate);
if (rc.IsFailure()) return rc;
throw new NotImplementedException();
switch (fsType)
{
case NcaFormatType.Romfs:
return FsCreators.RomFileSystemCreator.Create(out fileSystem, ncaSectionStorage);
case NcaFormatType.Pfs0:
return FsCreators.PartitionFileSystemCreator.Create(out fileSystem, ncaSectionStorage);
default:
return ResultFs.InvalidNcaFsType.Log();
}
}
/// <summary>
@ -340,9 +351,132 @@ namespace LibHac.FsService
return rc;
}
private Result TryOpenNca(ref U8Span path, out Nca nca, IFileSystem baseFileSystem, TitleId titleId)
private Result TryOpenNca(ref U8Span path, out Nca nca, IFileSystem baseFileSystem, TitleId programId)
{
throw new NotImplementedException();
nca = default;
Result rc = FileStorageBasedFileSystem.CreateNew(out FileStorageBasedFileSystem ncaFileStorage,
baseFileSystem, path, OpenMode.Read);
if (rc.IsFailure()) return rc;
rc = FsCreators.StorageOnNcaCreator.OpenNca(out Nca ncaTemp, ncaFileStorage);
if (rc.IsFailure()) return rc;
if (programId.Value == ulong.MaxValue)
{
ulong ncaProgramId = ncaTemp.Header.TitleId;
if (ncaProgramId != ulong.MaxValue && programId.Value != ncaProgramId)
{
return ResultFs.InvalidNcaProgramId.Log();
}
}
nca = ncaTemp;
return Result.Success;
}
private Result OpenNcaStorage(out IStorage ncaStorage, Nca nca, out NcaFormatType fsType,
FileSystemProxyType fsProxyType, bool isGameCard, bool canMountSystemDataPrivate)
{
ncaStorage = default;
fsType = default;
NcaContentType contentType = nca.Header.ContentType;
switch (fsProxyType)
{
case FileSystemProxyType.Code:
case FileSystemProxyType.Rom:
case FileSystemProxyType.Logo:
case FileSystemProxyType.RegisteredUpdate:
if (contentType != NcaContentType.Program)
return ResultFs.PreconditionViolation.Log();
break;
case FileSystemProxyType.Control:
if (contentType != NcaContentType.Control)
return ResultFs.PreconditionViolation.Log();
break;
case FileSystemProxyType.Manual:
if (contentType != NcaContentType.Manual)
return ResultFs.PreconditionViolation.Log();
break;
case FileSystemProxyType.Meta:
if (contentType != NcaContentType.Meta)
return ResultFs.PreconditionViolation.Log();
break;
case FileSystemProxyType.Data:
if (contentType != NcaContentType.Data && contentType != NcaContentType.PublicData)
return ResultFs.PreconditionViolation.Log();
if (contentType == NcaContentType.Data && !canMountSystemDataPrivate)
return ResultFs.PermissionDenied.Log();
break;
default:
return ResultFs.InvalidArgument.Log();
}
if (nca.Header.DistributionType == DistributionType.GameCard && !isGameCard)
return ResultFs.PermissionDenied.Log();
Result rc = SetNcaExternalKey(nca);
if (rc.IsFailure()) return rc;
rc = GetNcaSectionIndex(out int sectionIndex, fsProxyType);
if (rc.IsFailure()) return rc;
rc = FsCreators.StorageOnNcaCreator.Create(out ncaStorage, out NcaFsHeader fsHeader, nca,
sectionIndex, fsProxyType == FileSystemProxyType.Code);
if (rc.IsFailure()) return rc;
fsType = fsHeader.FormatType;
return Result.Success;
}
private Result SetNcaExternalKey(Nca nca)
{
var rightsId = new RightsId(nca.Header.RightsId);
var zero = new RightsId(0, 0);
if (Crypto.CryptoUtil.IsSameBytes(rightsId.AsBytes(), zero.AsBytes(), Unsafe.SizeOf<RightsId>()))
return Result.Success;
Result rc = ExternalKeys.Get(rightsId, out AccessKey accessKey);
if (rc.IsFailure()) return rc;
// todo: Set key in nca reader
return Result.Success;
}
private Result GetNcaSectionIndex(out int index, FileSystemProxyType fspType)
{
switch (fspType)
{
case FileSystemProxyType.Code:
case FileSystemProxyType.Control:
case FileSystemProxyType.Manual:
case FileSystemProxyType.Meta:
case FileSystemProxyType.Data:
index = 0;
return Result.Success;
case FileSystemProxyType.Rom:
case FileSystemProxyType.RegisteredUpdate:
index = 1;
return Result.Success;
case FileSystemProxyType.Logo:
index = 2;
return Result.Success;
default:
index = default;
return ResultFs.InvalidArgument.Log();
}
}
public Result OpenBisFileSystem(out IFileSystem fileSystem, string rootPath, BisPartitionId partitionId)