diff options
| author | Alex Barney <thealexbarney@gmail.com> | 2021-08-12 14:56:24 -0700 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2021-08-12 23:56:24 +0200 |
| commit | dadc0e59daa89c4dd7f0c3356f302481a4e75e6d (patch) | |
| tree | e39b6cd5198fef1fb2fe3461072b0961fd63502d /Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy | |
| parent | 3977d1f72b8f091443018b68277044a840931054 (diff) | |
Update to LibHac 0.13.1 (#2475)
* Update to LibHac 0.13.1
* Recreate directories for indexed saves if they're missing on emulator start
Diffstat (limited to 'Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy')
5 files changed, 117 insertions, 74 deletions
diff --git a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/FileSystemProxyHelper.cs b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/FileSystemProxyHelper.cs index 7774af23..1b6c84c3 100644 --- a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/FileSystemProxyHelper.cs +++ b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/FileSystemProxyHelper.cs @@ -1,10 +1,16 @@ using LibHac; using LibHac.Common; +using LibHac.Common.Keys; using LibHac.Fs; +using LibHac.FsSrv.Impl; +using LibHac.FsSrv.Sf; using LibHac.FsSystem; using LibHac.FsSystem.NcaUtils; using LibHac.Spl; +using System; using System.IO; +using System.Runtime.InteropServices; +using Path = System.IO.Path; namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { @@ -16,12 +22,12 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy try { - LocalStorage storage = new LocalStorage(pfsPath, FileAccess.Read, FileMode.Open); - PartitionFileSystem nsp = new PartitionFileSystem(storage); + LocalStorage storage = new LocalStorage(pfsPath, FileAccess.Read, FileMode.Open); + ReferenceCountedDisposable<LibHac.Fs.Fsa.IFileSystem> nsp = new(new PartitionFileSystem(storage)); - ImportTitleKeysFromNsp(nsp, context.Device.System.KeySet); + ImportTitleKeysFromNsp(nsp.Target, context.Device.System.KeySet); - openedFileSystem = new IFileSystem(nsp); + openedFileSystem = new IFileSystem(FileSystemInterfaceAdapter.CreateShared(ref nsp)); } catch (HorizonResultException ex) { @@ -45,8 +51,9 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy } LibHac.Fs.Fsa.IFileSystem fileSystem = nca.OpenFileSystem(NcaSectionType.Data, context.Device.System.FsIntegrityCheckLevel); + var sharedFs = new ReferenceCountedDisposable<LibHac.Fs.Fsa.IFileSystem>(fileSystem); - openedFileSystem = new IFileSystem(fileSystem); + openedFileSystem = new IFileSystem(FileSystemInterfaceAdapter.CreateShared(ref sharedFs)); } catch (HorizonResultException ex) { @@ -99,7 +106,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy return ResultCode.PathDoesNotExist; } - public static void ImportTitleKeysFromNsp(LibHac.Fs.Fsa.IFileSystem nsp, Keyset keySet) + public static void ImportTitleKeysFromNsp(LibHac.Fs.Fsa.IFileSystem nsp, KeySet keySet) { foreach (DirectoryEntryEx ticketEntry in nsp.EnumerateEntries("/", "*.tik")) { @@ -125,5 +132,27 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy return FsPath.FromSpan(out path, pathBytes); } + + public static ref readonly FspPath GetFspPath(ServiceCtx context, int index = 0) + { + ulong position = (ulong)context.Request.PtrBuff[index].Position; + ulong size = (ulong)context.Request.PtrBuff[index].Size; + + ReadOnlySpan<byte> buffer = context.Memory.GetSpan(position, (int)size); + ReadOnlySpan<FspPath> fspBuffer = MemoryMarshal.Cast<byte, FspPath>(buffer); + + return ref fspBuffer[0]; + } + + public static ref readonly LibHac.FsSrv.Sf.Path GetSfPath(ServiceCtx context, int index = 0) + { + ulong position = (ulong)context.Request.PtrBuff[index].Position; + ulong size = (ulong)context.Request.PtrBuff[index].Size; + + ReadOnlySpan<byte> buffer = context.Memory.GetSpan(position, (int)size); + ReadOnlySpan<LibHac.FsSrv.Sf.Path> pathBuffer = MemoryMarshal.Cast<byte, LibHac.FsSrv.Sf.Path>(buffer); + + return ref pathBuffer[0]; + } } } diff --git a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IDirectory.cs b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IDirectory.cs index 565ddc4c..99e545b1 100644 --- a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IDirectory.cs +++ b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IDirectory.cs @@ -1,15 +1,13 @@ using LibHac; -using LibHac.Fs; -using System; -using System.Runtime.InteropServices; +using LibHac.Sf; namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { - class IDirectory : IpcService + class IDirectory : DisposableIpcService { - private LibHac.Fs.Fsa.IDirectory _baseDirectory; + private ReferenceCountedDisposable<LibHac.FsSrv.Sf.IDirectory> _baseDirectory; - public IDirectory(LibHac.Fs.Fsa.IDirectory directory) + public IDirectory(ReferenceCountedDisposable<LibHac.FsSrv.Sf.IDirectory> directory) { _baseDirectory = directory; } @@ -19,14 +17,13 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy public ResultCode Read(ServiceCtx context) { ulong bufferPosition = context.Request.ReceiveBuff[0].Position; - ulong bufferLen = context.Request.ReceiveBuff[0].Size; + ulong bufferLen = context.Request.ReceiveBuff[0].Size; - byte[] entriesBytes = new byte[bufferLen]; - Span<DirectoryEntry> entries = MemoryMarshal.Cast<byte, DirectoryEntry>(entriesBytes); + byte[] entryBuffer = new byte[bufferLen]; - Result result = _baseDirectory.Read(out long entriesRead, entries); + Result result = _baseDirectory.Target.Read(out long entriesRead, new OutBuffer(entryBuffer)); - context.Memory.Write(bufferPosition, entriesBytes); + context.Memory.Write(bufferPosition, entryBuffer); context.ResponseData.Write(entriesRead); return (ResultCode)result.Value; @@ -36,11 +33,19 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy // GetEntryCount() -> u64 public ResultCode GetEntryCount(ServiceCtx context) { - Result result = _baseDirectory.GetEntryCount(out long entryCount); + Result result = _baseDirectory.Target.GetEntryCount(out long entryCount); context.ResponseData.Write(entryCount); return (ResultCode)result.Value; } + + protected override void Dispose(bool isDisposing) + { + if (isDisposing) + { + _baseDirectory?.Dispose(); + } + } } } diff --git a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFile.cs b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFile.cs index cf1611e7..3a94a2a7 100644 --- a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFile.cs +++ b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFile.cs @@ -1,13 +1,15 @@ using LibHac; using LibHac.Fs; +using LibHac.Sf; +using Ryujinx.Common; namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { class IFile : DisposableIpcService { - private LibHac.Fs.Fsa.IFile _baseFile; + private ReferenceCountedDisposable<LibHac.FsSrv.Sf.IFile> _baseFile; - public IFile(LibHac.Fs.Fsa.IFile baseFile) + public IFile(ReferenceCountedDisposable<LibHac.FsSrv.Sf.IFile> baseFile) { _baseFile = baseFile; } @@ -18,15 +20,15 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { ulong position = context.Request.ReceiveBuff[0].Position; - ReadOption readOption = new ReadOption(context.RequestData.ReadInt32()); + ReadOption readOption = context.RequestData.ReadStruct<ReadOption>(); context.RequestData.BaseStream.Position += 4; long offset = context.RequestData.ReadInt64(); long size = context.RequestData.ReadInt64(); - byte[] data = new byte[size]; + byte[] data = new byte[context.Request.ReceiveBuff[0].Size]; - Result result = _baseFile.Read(out long bytesRead, offset, data, readOption); + Result result = _baseFile.Target.Read(out long bytesRead, offset, new OutBuffer(data), size, readOption); context.Memory.Write(position, data); @@ -41,24 +43,24 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { ulong position = context.Request.SendBuff[0].Position; - WriteOption writeOption = new WriteOption(context.RequestData.ReadInt32()); + WriteOption writeOption = context.RequestData.ReadStruct<WriteOption>(); context.RequestData.BaseStream.Position += 4; long offset = context.RequestData.ReadInt64(); long size = context.RequestData.ReadInt64(); - byte[] data = new byte[size]; + byte[] data = new byte[context.Request.SendBuff[0].Size]; context.Memory.Read(position, data); - return (ResultCode)_baseFile.Write(offset, data, writeOption).Value; + return (ResultCode)_baseFile.Target.Write(offset, new InBuffer(data), size, writeOption).Value; } [CommandHipc(2)] // Flush() public ResultCode Flush(ServiceCtx context) { - return (ResultCode)_baseFile.Flush().Value; + return (ResultCode)_baseFile.Target.Flush().Value; } [CommandHipc(3)] @@ -67,14 +69,14 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { long size = context.RequestData.ReadInt64(); - return (ResultCode)_baseFile.SetSize(size).Value; + return (ResultCode)_baseFile.Target.SetSize(size).Value; } [CommandHipc(4)] // GetSize() -> u64 fileSize public ResultCode GetSize(ServiceCtx context) { - Result result = _baseFile.GetSize(out long size); + Result result = _baseFile.Target.GetSize(out long size); context.ResponseData.Write(size); diff --git a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs index 5aa26258..b9b4266d 100644 --- a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs +++ b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IFileSystem.cs @@ -1,21 +1,19 @@ using LibHac; -using LibHac.Common; using LibHac.Fs; -using LibHac.Fs.Fsa; -using static Ryujinx.HLE.Utilities.StringUtils; +using LibHac.FsSrv.Sf; namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { - class IFileSystem : IpcService + class IFileSystem : DisposableIpcService { - private LibHac.Fs.Fsa.IFileSystem _fileSystem; + private ReferenceCountedDisposable<LibHac.FsSrv.Sf.IFileSystem> _fileSystem; - public IFileSystem(LibHac.Fs.Fsa.IFileSystem provider) + public IFileSystem(ReferenceCountedDisposable<LibHac.FsSrv.Sf.IFileSystem> provider) { _fileSystem = provider; } - public LibHac.Fs.Fsa.IFileSystem GetBaseFileSystem() + public ReferenceCountedDisposable<LibHac.FsSrv.Sf.IFileSystem> GetBaseFileSystem() { return _fileSystem; } @@ -24,79 +22,79 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy // CreateFile(u32 createOption, u64 size, buffer<bytes<0x301>, 0x19, 0x301> path) public ResultCode CreateFile(ServiceCtx context) { - U8Span name = ReadUtf8Span(context); + ref readonly Path name = ref FileSystemProxyHelper.GetSfPath(context); - CreateFileOptions createOption = (CreateFileOptions)context.RequestData.ReadInt32(); + int createOption = context.RequestData.ReadInt32(); context.RequestData.BaseStream.Position += 4; long size = context.RequestData.ReadInt64(); - return (ResultCode)_fileSystem.CreateFile(name, size, createOption).Value; + return (ResultCode)_fileSystem.Target.CreateFile(in name, size, createOption).Value; } [CommandHipc(1)] // DeleteFile(buffer<bytes<0x301>, 0x19, 0x301> path) public ResultCode DeleteFile(ServiceCtx context) { - U8Span name = ReadUtf8Span(context); + ref readonly Path name = ref FileSystemProxyHelper.GetSfPath(context); - return (ResultCode)_fileSystem.DeleteFile(name).Value; + return (ResultCode)_fileSystem.Target.DeleteFile(in name).Value; } [CommandHipc(2)] // CreateDirectory(buffer<bytes<0x301>, 0x19, 0x301> path) public ResultCode CreateDirectory(ServiceCtx context) { - U8Span name = ReadUtf8Span(context); + ref readonly Path name = ref FileSystemProxyHelper.GetSfPath(context); - return (ResultCode)_fileSystem.CreateDirectory(name).Value; + return (ResultCode)_fileSystem.Target.CreateDirectory(in name).Value; } [CommandHipc(3)] // DeleteDirectory(buffer<bytes<0x301>, 0x19, 0x301> path) public ResultCode DeleteDirectory(ServiceCtx context) { - U8Span name = ReadUtf8Span(context); + ref readonly Path name = ref FileSystemProxyHelper.GetSfPath(context); - return (ResultCode)_fileSystem.DeleteDirectory(name).Value; + return (ResultCode)_fileSystem.Target.DeleteDirectory(in name).Value; } [CommandHipc(4)] // DeleteDirectoryRecursively(buffer<bytes<0x301>, 0x19, 0x301> path) public ResultCode DeleteDirectoryRecursively(ServiceCtx context) { - U8Span name = ReadUtf8Span(context); + ref readonly Path name = ref FileSystemProxyHelper.GetSfPath(context); - return (ResultCode)_fileSystem.DeleteDirectoryRecursively(name).Value; + return (ResultCode)_fileSystem.Target.DeleteDirectoryRecursively(in name).Value; } [CommandHipc(5)] // RenameFile(buffer<bytes<0x301>, 0x19, 0x301> oldPath, buffer<bytes<0x301>, 0x19, 0x301> newPath) public ResultCode RenameFile(ServiceCtx context) { - U8Span oldName = ReadUtf8Span(context, 0); - U8Span newName = ReadUtf8Span(context, 1); + ref readonly Path currentName = ref FileSystemProxyHelper.GetSfPath(context, index: 0); + ref readonly Path newName = ref FileSystemProxyHelper.GetSfPath(context, index: 1); - return (ResultCode)_fileSystem.RenameFile(oldName, newName).Value; + return (ResultCode)_fileSystem.Target.RenameFile(in currentName, in newName).Value; } [CommandHipc(6)] // RenameDirectory(buffer<bytes<0x301>, 0x19, 0x301> oldPath, buffer<bytes<0x301>, 0x19, 0x301> newPath) public ResultCode RenameDirectory(ServiceCtx context) { - U8Span oldName = ReadUtf8Span(context, 0); - U8Span newName = ReadUtf8Span(context, 1); + ref readonly Path currentName = ref FileSystemProxyHelper.GetSfPath(context, index: 0); + ref readonly Path newName = ref FileSystemProxyHelper.GetSfPath(context, index: 1); - return (ResultCode)_fileSystem.RenameDirectory(oldName, newName).Value; + return (ResultCode)_fileSystem.Target.RenameDirectory(in currentName, in newName).Value; } [CommandHipc(7)] // GetEntryType(buffer<bytes<0x301>, 0x19, 0x301> path) -> nn::fssrv::sf::DirectoryEntryType public ResultCode GetEntryType(ServiceCtx context) { - U8Span name = ReadUtf8Span(context); + ref readonly Path name = ref FileSystemProxyHelper.GetSfPath(context); - Result result = _fileSystem.GetEntryType(out DirectoryEntryType entryType, name); + Result result = _fileSystem.Target.GetEntryType(out uint entryType, in name); context.ResponseData.Write((int)entryType); @@ -107,11 +105,11 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy // OpenFile(u32 mode, buffer<bytes<0x301>, 0x19, 0x301> path) -> object<nn::fssrv::sf::IFile> file public ResultCode OpenFile(ServiceCtx context) { - OpenMode mode = (OpenMode)context.RequestData.ReadInt32(); + uint mode = context.RequestData.ReadUInt32(); - U8Span name = ReadUtf8Span(context); + ref readonly Path name = ref FileSystemProxyHelper.GetSfPath(context); - Result result = _fileSystem.OpenFile(out LibHac.Fs.Fsa.IFile file, name, mode); + Result result = _fileSystem.Target.OpenFile(out ReferenceCountedDisposable<LibHac.FsSrv.Sf.IFile> file, in name, mode); if (result.IsSuccess()) { @@ -127,11 +125,11 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy // OpenDirectory(u32 filter_flags, buffer<bytes<0x301>, 0x19, 0x301> path) -> object<nn::fssrv::sf::IDirectory> directory public ResultCode OpenDirectory(ServiceCtx context) { - OpenDirectoryMode mode = (OpenDirectoryMode)context.RequestData.ReadInt32(); + uint mode = context.RequestData.ReadUInt32(); - U8Span name = ReadUtf8Span(context); + ref readonly Path name = ref FileSystemProxyHelper.GetSfPath(context); - Result result = _fileSystem.OpenDirectory(out LibHac.Fs.Fsa.IDirectory dir, name, mode); + Result result = _fileSystem.Target.OpenDirectory(out ReferenceCountedDisposable<LibHac.FsSrv.Sf.IDirectory> dir, name, mode); if (result.IsSuccess()) { @@ -147,16 +145,16 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy // Commit() public ResultCode Commit(ServiceCtx context) { - return (ResultCode)_fileSystem.Commit().Value; + return (ResultCode)_fileSystem.Target.Commit().Value; } [CommandHipc(11)] // GetFreeSpaceSize(buffer<bytes<0x301>, 0x19, 0x301> path) -> u64 totalFreeSpace public ResultCode GetFreeSpaceSize(ServiceCtx context) { - U8Span name = ReadUtf8Span(context); + ref readonly Path name = ref FileSystemProxyHelper.GetSfPath(context); - Result result = _fileSystem.GetFreeSpaceSize(out long size, name); + Result result = _fileSystem.Target.GetFreeSpaceSize(out long size, in name); context.ResponseData.Write(size); @@ -167,9 +165,9 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy // GetTotalSpaceSize(buffer<bytes<0x301>, 0x19, 0x301> path) -> u64 totalSize public ResultCode GetTotalSpaceSize(ServiceCtx context) { - U8Span name = ReadUtf8Span(context); + ref readonly Path name = ref FileSystemProxyHelper.GetSfPath(context); - Result result = _fileSystem.GetTotalSpaceSize(out long size, name); + Result result = _fileSystem.Target.GetTotalSpaceSize(out long size, in name); context.ResponseData.Write(size); @@ -180,18 +178,18 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy // CleanDirectoryRecursively(buffer<bytes<0x301>, 0x19, 0x301> path) public ResultCode CleanDirectoryRecursively(ServiceCtx context) { - U8Span name = ReadUtf8Span(context); + ref readonly Path name = ref FileSystemProxyHelper.GetSfPath(context); - return (ResultCode)_fileSystem.CleanDirectoryRecursively(name).Value; + return (ResultCode)_fileSystem.Target.CleanDirectoryRecursively(in name).Value; } [CommandHipc(14)] // GetFileTimeStampRaw(buffer<bytes<0x301>, 0x19, 0x301> path) -> bytes<0x20> timestamp public ResultCode GetFileTimeStampRaw(ServiceCtx context) { - U8Span name = ReadUtf8Span(context); + ref readonly Path name = ref FileSystemProxyHelper.GetSfPath(context); - Result result = _fileSystem.GetFileTimeStampRaw(out FileTimeStampRaw timestamp, name); + Result result = _fileSystem.Target.GetFileTimeStampRaw(out FileTimeStampRaw timestamp, in name); context.ResponseData.Write(timestamp.Created); context.ResponseData.Write(timestamp.Modified); @@ -206,5 +204,13 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy return (ResultCode)result.Value; } + + protected override void Dispose(bool isDisposing) + { + if (isDisposing) + { + _fileSystem?.Dispose(); + } + } } }
\ No newline at end of file diff --git a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs index 62a3c62a..08f5b87b 100644 --- a/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs +++ b/Ryujinx.HLE/HOS/Services/Fs/FileSystemProxy/IStorage.cs @@ -1,13 +1,14 @@ using LibHac; +using LibHac.Sf; using Ryujinx.HLE.HOS.Ipc; namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy { class IStorage : DisposableIpcService { - private LibHac.Fs.IStorage _baseStorage; + private ReferenceCountedDisposable<LibHac.FsSrv.Sf.IStorage> _baseStorage; - public IStorage(LibHac.Fs.IStorage baseStorage) + public IStorage(ReferenceCountedDisposable<LibHac.FsSrv.Sf.IStorage> baseStorage) { _baseStorage = baseStorage; } @@ -31,7 +32,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy byte[] data = new byte[size]; - Result result = _baseStorage.Read((long)offset, data); + Result result = _baseStorage.Target.Read((long)offset, new OutBuffer(data), (long)size); context.Memory.Write(buffDesc.Position, data); @@ -45,7 +46,7 @@ namespace Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy // GetSize() -> u64 size public ResultCode GetSize(ServiceCtx context) { - Result result = _baseStorage.GetSize(out long size); + Result result = _baseStorage.Target.GetSize(out long size); context.ResponseData.Write(size); |
