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,4464,,AllocationTableIteratedRangeEntry,
|
||||||
|
|
||||||
2,4501,4599,NcaCorrupted,
|
2,4501,4599,NcaCorrupted,
|
||||||
|
2,4512,,InvalidNcaFsType,
|
||||||
|
2,4527,,InvalidNcaProgramId,
|
||||||
|
|
||||||
2,4601,4639,IntegrityVerificationStorageCorrupted,
|
2,4601,4639,IntegrityVerificationStorageCorrupted,
|
||||||
2,4602,,InvalidIvfcMagic,
|
2,4602,,InvalidIvfcMagic,
|
||||||
|
|
|
|
@ -6,10 +6,10 @@ namespace LibHac.Fs
|
||||||
{
|
{
|
||||||
public class FileStorage2 : StorageBase
|
public class FileStorage2 : StorageBase
|
||||||
{
|
{
|
||||||
private const long InvalidSize = -1;
|
protected const long InvalidSize = -1;
|
||||||
|
|
||||||
private IFile BaseFile { get; set; }
|
private IFile BaseFile { get; set; }
|
||||||
private long FileSize { get; set; }
|
protected long FileSize { get; set; }
|
||||||
|
|
||||||
public FileStorage2(IFile baseFile)
|
public FileStorage2(IFile baseFile)
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,7 +9,10 @@ namespace LibHac.Fs
|
||||||
private IFileSystem BaseFileSystem { get; set; }
|
private IFileSystem BaseFileSystem { get; set; }
|
||||||
private IFile BaseFile { get; set; }
|
private IFile BaseFile { get; set; }
|
||||||
|
|
||||||
private FileStorageBasedFileSystem() { }
|
private FileStorageBasedFileSystem()
|
||||||
|
{
|
||||||
|
FileSize = InvalidSize;
|
||||||
|
}
|
||||||
|
|
||||||
public static Result CreateNew(out FileStorageBasedFileSystem created, IFileSystem baseFileSystem, U8Span path,
|
public static Result CreateNew(out FileStorageBasedFileSystem created, IFileSystem baseFileSystem, U8Span path,
|
||||||
OpenMode mode)
|
OpenMode mode)
|
||||||
|
|
|
@ -171,6 +171,10 @@ namespace LibHac.Fs
|
||||||
|
|
||||||
/// <summary>Error code: 2002-4501; Range: 4501-4599; Inner value: 0x232a02</summary>
|
/// <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); }
|
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>
|
/// <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); }
|
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
|
namespace LibHac.FsService.Creators
|
||||||
{
|
{
|
||||||
public class RomFileSystemCreator : IRomFileSystemCreator
|
public class RomFileSystemCreator : IRomFileSystemCreator
|
||||||
{
|
{
|
||||||
|
// todo: Implement properly
|
||||||
public Result Create(out IFileSystem fileSystem, IStorage romFsStorage)
|
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 System;
|
||||||
using LibHac.Fs;
|
using LibHac.Fs;
|
||||||
|
using LibHac.FsSystem;
|
||||||
|
using LibHac.FsSystem.Detail;
|
||||||
using LibHac.FsSystem.NcaUtils;
|
using LibHac.FsSystem.NcaUtils;
|
||||||
|
|
||||||
namespace LibHac.FsService.Creators
|
namespace LibHac.FsService.Creators
|
||||||
{
|
{
|
||||||
public class StorageOnNcaCreator : IStorageOnNcaCreator
|
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)
|
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)
|
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)
|
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)
|
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.RomFileSystemCreator = new RomFileSystemCreator();
|
||||||
creators.PartitionFileSystemCreator = new PartitionFileSystemCreator();
|
creators.PartitionFileSystemCreator = new PartitionFileSystemCreator();
|
||||||
creators.StorageOnNcaCreator = new StorageOnNcaCreator();
|
creators.StorageOnNcaCreator = new StorageOnNcaCreator(keyset);
|
||||||
creators.TargetManagerFileSystemCreator = new TargetManagerFileSystemCreator();
|
creators.TargetManagerFileSystemCreator = new TargetManagerFileSystemCreator();
|
||||||
creators.SubDirectoryFileSystemCreator = new SubDirectoryFileSystemCreator();
|
creators.SubDirectoryFileSystemCreator = new SubDirectoryFileSystemCreator();
|
||||||
creators.SaveDataFileSystemCreator = new SaveDataFileSystemCreator(keyset);
|
creators.SaveDataFileSystemCreator = new SaveDataFileSystemCreator(keyset);
|
||||||
|
|
|
@ -40,11 +40,22 @@ namespace LibHac.FsService
|
||||||
|
|
||||||
bool canMountSystemDataPrivate = false;
|
bool canMountSystemDataPrivate = false;
|
||||||
|
|
||||||
Result rc = PathTools.Normalize(out U8Span normalizedPath, path);
|
var normalizer = new PathNormalizer(path, GetPathNormalizerOptions(path));
|
||||||
if (rc.IsFailure()) return rc;
|
if (normalizer.Result.IsFailure()) return normalizer.Result;
|
||||||
|
|
||||||
// ReSharper disable once ConditionIsAlwaysTrueOrFalse
|
// 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)
|
public Result OpenFileSystemWithPatch(out IFileSystem fileSystem, TitleId titleId, FileSystemProxyType type)
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
using LibHac.Common;
|
using LibHac.Common;
|
||||||
using LibHac.Fs;
|
using LibHac.Fs;
|
||||||
using LibHac.Fs.Shim;
|
using LibHac.Fs.Shim;
|
||||||
|
@ -96,9 +97,19 @@ namespace LibHac.FsService
|
||||||
rc = TryOpenNca(ref path2, out Nca nca, baseFileSystem, openTitleId);
|
rc = TryOpenNca(ref path2, out Nca nca, baseFileSystem, openTitleId);
|
||||||
if (rc.IsFailure()) return rc;
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
|
rc = OpenNcaStorage(out IStorage ncaSectionStorage, nca, out NcaFormatType fsType, type,
|
||||||
|
mountNameInfo.IsGameCard, canMountSystemDataPrivate);
|
||||||
|
if (rc.IsFailure()) return rc;
|
||||||
|
|
||||||
|
switch (fsType)
|
||||||
throw new NotImplementedException();
|
{
|
||||||
|
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>
|
/// <summary>
|
||||||
|
@ -340,9 +351,132 @@ namespace LibHac.FsService
|
||||||
return rc;
|
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)
|
public Result OpenBisFileSystem(out IFileSystem fileSystem, string rootPath, BisPartitionId partitionId)
|
||||||
|
|
Loading…
Reference in a new issue