mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Finish OpenFileSystemWithId enough to work with most content
This commit is contained in:
parent
281fc8aac3
commit
036e048208
9 changed files with 219 additions and 18 deletions
|
@ -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,
|
||||
|
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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); }
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in a new issue