ryujinx/Ryujinx.HLE/HOS/Services/Fs/IFileSystemProxy.cs

571 lines
23 KiB
C#
Raw Normal View History

using LibHac;
using LibHac.Fs;
using LibHac.FsSrv;
using LibHac.FsSystem;
using LibHac.FsSystem.NcaUtils;
using LibHac.Ncm;
using Ryujinx.Common;
using Ryujinx.Common.Logging;
using Ryujinx.Cpu;
using Ryujinx.HLE.HOS.Services.Fs.FileSystemProxy;
using System.IO;
using static Ryujinx.HLE.Utilities.StringUtils;
using StorageId = Ryujinx.HLE.FileSystem.StorageId;
namespace Ryujinx.HLE.HOS.Services.Fs
{
[Service("fsp-srv")]
class IFileSystemProxy : IpcService
{
private LibHac.FsSrv.IFileSystemProxy _baseFileSystemProxy;
public IFileSystemProxy(ServiceCtx context)
{
_baseFileSystemProxy = context.Device.FileSystem.FsServer.CreateFileSystemProxyService();
}
[CommandHipc(1)]
// Initialize(u64, pid)
public ResultCode Initialize(ServiceCtx context)
{
return ResultCode.Success;
}
[CommandHipc(8)]
// OpenFileSystemWithId(nn::fssrv::sf::FileSystemType filesystem_type, nn::ApplicationId tid, buffer<bytes<0x301>, 0x19, 0x301> path)
// -> object<nn::fssrv::sf::IFileSystem> contentFs
public ResultCode OpenFileSystemWithId(ServiceCtx context)
{
FileSystemType fileSystemType = (FileSystemType)context.RequestData.ReadInt32();
ulong titleId = context.RequestData.ReadUInt64();
string switchPath = ReadUtf8String(context);
string fullPath = context.Device.FileSystem.SwitchPathToSystemPath(switchPath);
if (!File.Exists(fullPath))
{
if (fullPath.Contains("."))
{
ResultCode result = FileSystemProxyHelper.OpenFileSystemFromInternalFile(context, fullPath, out FileSystemProxy.IFileSystem fileSystem);
if (result == ResultCode.Success)
{
MakeObject(context, fileSystem);
}
return result;
}
return ResultCode.PathDoesNotExist;
}
FileStream fileStream = new FileStream(fullPath, FileMode.Open, FileAccess.Read);
string extension = Path.GetExtension(fullPath);
if (extension == ".nca")
{
ResultCode result = FileSystemProxyHelper.OpenNcaFs(context, fullPath, fileStream.AsStorage(), out FileSystemProxy.IFileSystem fileSystem);
if (result == ResultCode.Success)
{
MakeObject(context, fileSystem);
}
return result;
}
else if (extension == ".nsp")
{
ResultCode result = FileSystemProxyHelper.OpenNsp(context, fullPath, out FileSystemProxy.IFileSystem fileSystem);
if (result == ResultCode.Success)
{
MakeObject(context, fileSystem);
}
return result;
}
return ResultCode.InvalidInput;
}
[CommandHipc(11)]
// OpenBisFileSystem(nn::fssrv::sf::Partition partitionID, buffer<bytes<0x301>, 0x19, 0x301>) -> object<nn::fssrv::sf::IFileSystem> Bis
public ResultCode OpenBisFileSystem(ServiceCtx context)
{
BisPartitionId bisPartitionId = (BisPartitionId)context.RequestData.ReadInt32();
Result rc = FileSystemProxyHelper.ReadFsPath(out FsPath path, context);
if (rc.IsFailure()) return (ResultCode)rc.Value;
rc = _baseFileSystemProxy.OpenBisFileSystem(out LibHac.Fs.Fsa.IFileSystem fileSystem, ref path, bisPartitionId);
if (rc.IsFailure()) return (ResultCode)rc.Value;
MakeObject(context, new FileSystemProxy.IFileSystem(fileSystem));
return ResultCode.Success;
}
[CommandHipc(18)]
// OpenSdCardFileSystem() -> object<nn::fssrv::sf::IFileSystem>
public ResultCode OpenSdCardFileSystem(ServiceCtx context)
{
Result rc = _baseFileSystemProxy.OpenSdCardFileSystem(out LibHac.Fs.Fsa.IFileSystem fileSystem);
if (rc.IsFailure()) return (ResultCode)rc.Value;
MakeObject(context, new FileSystemProxy.IFileSystem(fileSystem));
return ResultCode.Success;
}
[CommandHipc(21)]
public ResultCode DeleteSaveDataFileSystem(ServiceCtx context)
{
ulong saveDataId = context.RequestData.ReadUInt64();
Result result = _baseFileSystemProxy.DeleteSaveDataFileSystem(saveDataId);
return (ResultCode)result.Value;
}
[CommandHipc(22)]
public ResultCode CreateSaveDataFileSystem(ServiceCtx context)
{
SaveDataAttribute attribute = context.RequestData.ReadStruct<SaveDataAttribute>();
SaveDataCreationInfo creationInfo = context.RequestData.ReadStruct<SaveDataCreationInfo>();
SaveMetaCreateInfo metaCreateInfo = context.RequestData.ReadStruct<SaveMetaCreateInfo>();
// TODO: There's currently no program registry for FS to reference.
// Workaround that by setting the application ID and owner ID if they're not already set
if (attribute.ProgramId == ProgramId.InvalidId)
{
attribute.ProgramId = new ProgramId(context.Device.Application.TitleId);
}
Logger.Info?.Print(LogClass.ServiceFs, $"Creating save with title ID {attribute.ProgramId.Value:x16}");
Result result = _baseFileSystemProxy.CreateSaveDataFileSystem(ref attribute, ref creationInfo, ref metaCreateInfo);
return (ResultCode)result.Value;
}
[CommandHipc(23)]
public ResultCode CreateSaveDataFileSystemBySystemSaveDataId(ServiceCtx context)
{
SaveDataAttribute attribute = context.RequestData.ReadStruct<SaveDataAttribute>();
SaveDataCreationInfo creationInfo = context.RequestData.ReadStruct<SaveDataCreationInfo>();
Result result = _baseFileSystemProxy.CreateSaveDataFileSystemBySystemSaveDataId(ref attribute, ref creationInfo);
return (ResultCode)result.Value;
}
[CommandHipc(25)]
public ResultCode DeleteSaveDataFileSystemBySaveDataSpaceId(ServiceCtx context)
{
SaveDataSpaceId spaceId = (SaveDataSpaceId)context.RequestData.ReadInt64();
ulong saveDataId = context.RequestData.ReadUInt64();
Result result = _baseFileSystemProxy.DeleteSaveDataFileSystemBySaveDataSpaceId(spaceId, saveDataId);
return (ResultCode)result.Value;
}
[CommandHipc(28)]
public ResultCode DeleteSaveDataFileSystemBySaveDataAttribute(ServiceCtx context)
{
SaveDataSpaceId spaceId = (SaveDataSpaceId)context.RequestData.ReadInt64();
SaveDataAttribute attribute = context.RequestData.ReadStruct<SaveDataAttribute>();
Result result = _baseFileSystemProxy.DeleteSaveDataFileSystemBySaveDataAttribute(spaceId, ref attribute);
return (ResultCode)result.Value;
}
[CommandHipc(30)]
// OpenGameCardStorage(u32, u32) -> object<nn::fssrv::sf::IStorage>
public ResultCode OpenGameCardStorage(ServiceCtx context)
{
GameCardHandle handle = new GameCardHandle(context.RequestData.ReadInt32());
GameCardPartitionRaw partitionId = (GameCardPartitionRaw)context.RequestData.ReadInt32();
Result result = _baseFileSystemProxy.OpenGameCardStorage(out LibHac.Fs.IStorage storage, handle, partitionId);
Update to LibHac 0.13.1 (#2328) Update the LibHac dependency to version 0.13.1. This brings a ton of improvements and changes such as: - Refactor `FsSrv` to match the official refactoring done in FS. - Change how the `Horizon` and `HorizonClient` classes are handled. Each client created represents a different process with its own process ID and client state. - Add FS access control to handle permissions for FS service method calls. - Add FS program registry to keep track of the program ID, location and permissions of each process. - Add FS program index map info manager to track the program IDs and indexes of multi-application programs. - Add all FS IPC interfaces. - Rewrite `Fs.Fsa` code to be more accurate. - Rewrite a lot of `FsSrv` code to be more accurate. - Extend directory save data to store `SaveDataExtraData` - Extend directory save data to lock the save directory to allow only one accessor at a time. - Improve waiting and retrying when encountering access issues in `LocalFileSystem` and `DirectorySaveDataFileSystem`. - More `IFileSystemProxy` methods should work now. - Probably a bunch more stuff. On the Ryujinx side: - Forward most `IFileSystemProxy` methods to LibHac. - Register programs and program index map info when launching an application. - Remove hacks and workarounds for missing LibHac functionality. - Recreate missing save data extra data found on emulator startup. - Create system save data that wasn't indexed correctly on an older LibHac version. `FsSrv` now enforces access control for each process. When a process tries to open a save data file system, FS reads the save's extra data to determine who the save owner is and if the caller has permission to open the save data. Previously-created save data did not have extra data created when the save was created. With access control checks in place, this means that processes with no permissions (most games) wouldn't be able to access their own save data. The extra data can be partially created from data in the save data indexer, which should be enough for access control purposes.
2021-07-13 10:19:28 +02:00
if (result.IsSuccess())
{
MakeObject(context, new FileSystemProxy.IStorage(storage));
}
Update to LibHac 0.13.1 (#2328) Update the LibHac dependency to version 0.13.1. This brings a ton of improvements and changes such as: - Refactor `FsSrv` to match the official refactoring done in FS. - Change how the `Horizon` and `HorizonClient` classes are handled. Each client created represents a different process with its own process ID and client state. - Add FS access control to handle permissions for FS service method calls. - Add FS program registry to keep track of the program ID, location and permissions of each process. - Add FS program index map info manager to track the program IDs and indexes of multi-application programs. - Add all FS IPC interfaces. - Rewrite `Fs.Fsa` code to be more accurate. - Rewrite a lot of `FsSrv` code to be more accurate. - Extend directory save data to store `SaveDataExtraData` - Extend directory save data to lock the save directory to allow only one accessor at a time. - Improve waiting and retrying when encountering access issues in `LocalFileSystem` and `DirectorySaveDataFileSystem`. - More `IFileSystemProxy` methods should work now. - Probably a bunch more stuff. On the Ryujinx side: - Forward most `IFileSystemProxy` methods to LibHac. - Register programs and program index map info when launching an application. - Remove hacks and workarounds for missing LibHac functionality. - Recreate missing save data extra data found on emulator startup. - Create system save data that wasn't indexed correctly on an older LibHac version. `FsSrv` now enforces access control for each process. When a process tries to open a save data file system, FS reads the save's extra data to determine who the save owner is and if the caller has permission to open the save data. Previously-created save data did not have extra data created when the save was created. With access control checks in place, this means that processes with no permissions (most games) wouldn't be able to access their own save data. The extra data can be partially created from data in the save data indexer, which should be enough for access control purposes.
2021-07-13 10:19:28 +02:00
return (ResultCode)result.Value;
}
[CommandHipc(35)]
public ResultCode CreateSaveDataFileSystemWithHashSalt(ServiceCtx context)
{
SaveDataAttribute attribute = context.RequestData.ReadStruct<SaveDataAttribute>();
SaveDataCreationInfo creationInfo = context.RequestData.ReadStruct<SaveDataCreationInfo>();
SaveMetaCreateInfo metaCreateInfo = context.RequestData.ReadStruct<SaveMetaCreateInfo>();
HashSalt hashSalt = context.RequestData.ReadStruct<HashSalt>();
// TODO: There's currently no program registry for FS to reference.
// Workaround that by setting the application ID and owner ID if they're not already set
if (attribute.ProgramId == ProgramId.InvalidId)
{
attribute.ProgramId = new ProgramId(context.Device.Application.TitleId);
}
Result result = _baseFileSystemProxy.CreateSaveDataFileSystemWithHashSalt(ref attribute, ref creationInfo, ref metaCreateInfo, ref hashSalt);
return (ResultCode)result.Value;
}
[CommandHipc(51)]
// OpenSaveDataFileSystem(u8 save_data_space_id, nn::fssrv::sf::SaveStruct saveStruct) -> object<nn::fssrv::sf::IFileSystem> saveDataFs
public ResultCode OpenSaveDataFileSystem(ServiceCtx context)
{
SaveDataSpaceId spaceId = (SaveDataSpaceId)context.RequestData.ReadInt64();
SaveDataAttribute attribute = context.RequestData.ReadStruct<SaveDataAttribute>();
// TODO: There's currently no program registry for FS to reference.
// Workaround that by setting the application ID if it's not already set
if (attribute.ProgramId == ProgramId.InvalidId)
{
attribute.ProgramId = new ProgramId(context.Device.Application.TitleId);
}
Result result = _baseFileSystemProxy.OpenSaveDataFileSystem(out LibHac.Fs.Fsa.IFileSystem fileSystem, spaceId, ref attribute);
if (result.IsSuccess())
{
MakeObject(context, new FileSystemProxy.IFileSystem(fileSystem));
}
return (ResultCode)result.Value;
}
[CommandHipc(52)]
// OpenSaveDataFileSystemBySystemSaveDataId(u8 save_data_space_id, nn::fssrv::sf::SaveStruct saveStruct) -> object<nn::fssrv::sf::IFileSystem> systemSaveDataFs
public ResultCode OpenSaveDataFileSystemBySystemSaveDataId(ServiceCtx context)
{
SaveDataSpaceId spaceId = (SaveDataSpaceId)context.RequestData.ReadInt64();
SaveDataAttribute attribute = context.RequestData.ReadStruct<SaveDataAttribute>();
Result result = _baseFileSystemProxy.OpenSaveDataFileSystemBySystemSaveDataId(out LibHac.Fs.Fsa.IFileSystem fileSystem, spaceId, ref attribute);
if (result.IsSuccess())
{
MakeObject(context, new FileSystemProxy.IFileSystem(fileSystem));
}
return (ResultCode)result.Value;
}
[CommandHipc(53)]
// OpenReadOnlySaveDataFileSystem(u8 save_data_space_id, nn::fssrv::sf::SaveStruct save_struct) -> object<nn::fssrv::sf::IFileSystem>
public ResultCode OpenReadOnlySaveDataFileSystem(ServiceCtx context)
{
SaveDataSpaceId spaceId = (SaveDataSpaceId)context.RequestData.ReadInt64();
SaveDataAttribute attribute = context.RequestData.ReadStruct<SaveDataAttribute>();
// TODO: There's currently no program registry for FS to reference.
// Workaround that by setting the application ID if it's not already set
if (attribute.ProgramId == ProgramId.InvalidId)
{
attribute.ProgramId = new ProgramId(context.Device.Application.TitleId);
}
Update to LibHac 0.13.1 (#2328) Update the LibHac dependency to version 0.13.1. This brings a ton of improvements and changes such as: - Refactor `FsSrv` to match the official refactoring done in FS. - Change how the `Horizon` and `HorizonClient` classes are handled. Each client created represents a different process with its own process ID and client state. - Add FS access control to handle permissions for FS service method calls. - Add FS program registry to keep track of the program ID, location and permissions of each process. - Add FS program index map info manager to track the program IDs and indexes of multi-application programs. - Add all FS IPC interfaces. - Rewrite `Fs.Fsa` code to be more accurate. - Rewrite a lot of `FsSrv` code to be more accurate. - Extend directory save data to store `SaveDataExtraData` - Extend directory save data to lock the save directory to allow only one accessor at a time. - Improve waiting and retrying when encountering access issues in `LocalFileSystem` and `DirectorySaveDataFileSystem`. - More `IFileSystemProxy` methods should work now. - Probably a bunch more stuff. On the Ryujinx side: - Forward most `IFileSystemProxy` methods to LibHac. - Register programs and program index map info when launching an application. - Remove hacks and workarounds for missing LibHac functionality. - Recreate missing save data extra data found on emulator startup. - Create system save data that wasn't indexed correctly on an older LibHac version. `FsSrv` now enforces access control for each process. When a process tries to open a save data file system, FS reads the save's extra data to determine who the save owner is and if the caller has permission to open the save data. Previously-created save data did not have extra data created when the save was created. With access control checks in place, this means that processes with no permissions (most games) wouldn't be able to access their own save data. The extra data can be partially created from data in the save data indexer, which should be enough for access control purposes.
2021-07-13 10:19:28 +02:00
Result result = _baseFileSystemProxy.OpenReadOnlySaveDataFileSystem(out LibHac.Fs.Fsa.IFileSystem fileSystem, spaceId, ref attribute);
Update to LibHac 0.13.1 (#2328) Update the LibHac dependency to version 0.13.1. This brings a ton of improvements and changes such as: - Refactor `FsSrv` to match the official refactoring done in FS. - Change how the `Horizon` and `HorizonClient` classes are handled. Each client created represents a different process with its own process ID and client state. - Add FS access control to handle permissions for FS service method calls. - Add FS program registry to keep track of the program ID, location and permissions of each process. - Add FS program index map info manager to track the program IDs and indexes of multi-application programs. - Add all FS IPC interfaces. - Rewrite `Fs.Fsa` code to be more accurate. - Rewrite a lot of `FsSrv` code to be more accurate. - Extend directory save data to store `SaveDataExtraData` - Extend directory save data to lock the save directory to allow only one accessor at a time. - Improve waiting and retrying when encountering access issues in `LocalFileSystem` and `DirectorySaveDataFileSystem`. - More `IFileSystemProxy` methods should work now. - Probably a bunch more stuff. On the Ryujinx side: - Forward most `IFileSystemProxy` methods to LibHac. - Register programs and program index map info when launching an application. - Remove hacks and workarounds for missing LibHac functionality. - Recreate missing save data extra data found on emulator startup. - Create system save data that wasn't indexed correctly on an older LibHac version. `FsSrv` now enforces access control for each process. When a process tries to open a save data file system, FS reads the save's extra data to determine who the save owner is and if the caller has permission to open the save data. Previously-created save data did not have extra data created when the save was created. With access control checks in place, this means that processes with no permissions (most games) wouldn't be able to access their own save data. The extra data can be partially created from data in the save data indexer, which should be enough for access control purposes.
2021-07-13 10:19:28 +02:00
if (result.IsSuccess())
{
MakeObject(context, new FileSystemProxy.IFileSystem(fileSystem));
}
Update to LibHac 0.13.1 (#2328) Update the LibHac dependency to version 0.13.1. This brings a ton of improvements and changes such as: - Refactor `FsSrv` to match the official refactoring done in FS. - Change how the `Horizon` and `HorizonClient` classes are handled. Each client created represents a different process with its own process ID and client state. - Add FS access control to handle permissions for FS service method calls. - Add FS program registry to keep track of the program ID, location and permissions of each process. - Add FS program index map info manager to track the program IDs and indexes of multi-application programs. - Add all FS IPC interfaces. - Rewrite `Fs.Fsa` code to be more accurate. - Rewrite a lot of `FsSrv` code to be more accurate. - Extend directory save data to store `SaveDataExtraData` - Extend directory save data to lock the save directory to allow only one accessor at a time. - Improve waiting and retrying when encountering access issues in `LocalFileSystem` and `DirectorySaveDataFileSystem`. - More `IFileSystemProxy` methods should work now. - Probably a bunch more stuff. On the Ryujinx side: - Forward most `IFileSystemProxy` methods to LibHac. - Register programs and program index map info when launching an application. - Remove hacks and workarounds for missing LibHac functionality. - Recreate missing save data extra data found on emulator startup. - Create system save data that wasn't indexed correctly on an older LibHac version. `FsSrv` now enforces access control for each process. When a process tries to open a save data file system, FS reads the save's extra data to determine who the save owner is and if the caller has permission to open the save data. Previously-created save data did not have extra data created when the save was created. With access control checks in place, this means that processes with no permissions (most games) wouldn't be able to access their own save data. The extra data can be partially created from data in the save data indexer, which should be enough for access control purposes.
2021-07-13 10:19:28 +02:00
return (ResultCode)result.Value;
}
[CommandHipc(60)]
public ResultCode OpenSaveDataInfoReader(ServiceCtx context)
{
Result result = _baseFileSystemProxy.OpenSaveDataInfoReader(out ReferenceCountedDisposable<LibHac.FsSrv.ISaveDataInfoReader> infoReader);
if (result.IsSuccess())
{
MakeObject(context, new ISaveDataInfoReader(infoReader));
}
return (ResultCode)result.Value;
}
[CommandHipc(61)]
public ResultCode OpenSaveDataInfoReaderBySaveDataSpaceId(ServiceCtx context)
{
SaveDataSpaceId spaceId = (SaveDataSpaceId)context.RequestData.ReadByte();
Result result = _baseFileSystemProxy.OpenSaveDataInfoReaderBySaveDataSpaceId(out ReferenceCountedDisposable<LibHac.FsSrv.ISaveDataInfoReader> infoReader, spaceId);
if (result.IsSuccess())
{
MakeObject(context, new ISaveDataInfoReader(infoReader));
}
return (ResultCode)result.Value;
}
[CommandHipc(62)]
public ResultCode OpenSaveDataInfoReaderOnlyCacheStorage(ServiceCtx context)
{
SaveDataFilter filter = new SaveDataFilter();
filter.SetSaveDataType(SaveDataType.Cache);
filter.SetProgramId(new ProgramId(context.Process.TitleId));
Update to LibHac 0.13.1 (#2328) Update the LibHac dependency to version 0.13.1. This brings a ton of improvements and changes such as: - Refactor `FsSrv` to match the official refactoring done in FS. - Change how the `Horizon` and `HorizonClient` classes are handled. Each client created represents a different process with its own process ID and client state. - Add FS access control to handle permissions for FS service method calls. - Add FS program registry to keep track of the program ID, location and permissions of each process. - Add FS program index map info manager to track the program IDs and indexes of multi-application programs. - Add all FS IPC interfaces. - Rewrite `Fs.Fsa` code to be more accurate. - Rewrite a lot of `FsSrv` code to be more accurate. - Extend directory save data to store `SaveDataExtraData` - Extend directory save data to lock the save directory to allow only one accessor at a time. - Improve waiting and retrying when encountering access issues in `LocalFileSystem` and `DirectorySaveDataFileSystem`. - More `IFileSystemProxy` methods should work now. - Probably a bunch more stuff. On the Ryujinx side: - Forward most `IFileSystemProxy` methods to LibHac. - Register programs and program index map info when launching an application. - Remove hacks and workarounds for missing LibHac functionality. - Recreate missing save data extra data found on emulator startup. - Create system save data that wasn't indexed correctly on an older LibHac version. `FsSrv` now enforces access control for each process. When a process tries to open a save data file system, FS reads the save's extra data to determine who the save owner is and if the caller has permission to open the save data. Previously-created save data did not have extra data created when the save was created. With access control checks in place, this means that processes with no permissions (most games) wouldn't be able to access their own save data. The extra data can be partially created from data in the save data indexer, which should be enough for access control purposes.
2021-07-13 10:19:28 +02:00
// FS would query the User and SdCache space IDs to find where the existing cache is (if any).
// We always have the SD card inserted, so we can always use SdCache for now.
Result result = _baseFileSystemProxy.OpenSaveDataInfoReaderBySaveDataSpaceId(
out ReferenceCountedDisposable<LibHac.FsSrv.ISaveDataInfoReader> infoReader, SaveDataSpaceId.SdCache);
Update to LibHac 0.13.1 (#2328) Update the LibHac dependency to version 0.13.1. This brings a ton of improvements and changes such as: - Refactor `FsSrv` to match the official refactoring done in FS. - Change how the `Horizon` and `HorizonClient` classes are handled. Each client created represents a different process with its own process ID and client state. - Add FS access control to handle permissions for FS service method calls. - Add FS program registry to keep track of the program ID, location and permissions of each process. - Add FS program index map info manager to track the program IDs and indexes of multi-application programs. - Add all FS IPC interfaces. - Rewrite `Fs.Fsa` code to be more accurate. - Rewrite a lot of `FsSrv` code to be more accurate. - Extend directory save data to store `SaveDataExtraData` - Extend directory save data to lock the save directory to allow only one accessor at a time. - Improve waiting and retrying when encountering access issues in `LocalFileSystem` and `DirectorySaveDataFileSystem`. - More `IFileSystemProxy` methods should work now. - Probably a bunch more stuff. On the Ryujinx side: - Forward most `IFileSystemProxy` methods to LibHac. - Register programs and program index map info when launching an application. - Remove hacks and workarounds for missing LibHac functionality. - Recreate missing save data extra data found on emulator startup. - Create system save data that wasn't indexed correctly on an older LibHac version. `FsSrv` now enforces access control for each process. When a process tries to open a save data file system, FS reads the save's extra data to determine who the save owner is and if the caller has permission to open the save data. Previously-created save data did not have extra data created when the save was created. With access control checks in place, this means that processes with no permissions (most games) wouldn't be able to access their own save data. The extra data can be partially created from data in the save data indexer, which should be enough for access control purposes.
2021-07-13 10:19:28 +02:00
if (result.IsSuccess())
{
MakeObject(context, new ISaveDataInfoReader(infoReader));
}
return (ResultCode)result.Value;
}
[CommandHipc(67)]
public ResultCode FindSaveDataWithFilter(ServiceCtx context)
{
SaveDataSpaceId spaceId = (SaveDataSpaceId)context.RequestData.ReadInt64();
SaveDataFilter filter = context.RequestData.ReadStruct<SaveDataFilter>();
ulong bufferPosition = context.Request.ReceiveBuff[0].Position;
ulong bufferLen = context.Request.ReceiveBuff[0].Size;
byte[] infoBuffer = new byte[bufferLen];
Result result = _baseFileSystemProxy.FindSaveDataWithFilter(out long count, infoBuffer, spaceId, ref filter);
context.Memory.Write(bufferPosition, infoBuffer);
context.ResponseData.Write(count);
return (ResultCode)result.Value;
}
[CommandHipc(68)]
public ResultCode OpenSaveDataInfoReaderWithFilter(ServiceCtx context)
{
SaveDataSpaceId spaceId = (SaveDataSpaceId)context.RequestData.ReadInt64();
SaveDataFilter filter = context.RequestData.ReadStruct<SaveDataFilter>();
Result result = _baseFileSystemProxy.OpenSaveDataInfoReaderWithFilter(
out ReferenceCountedDisposable<LibHac.FsSrv.ISaveDataInfoReader> infoReader, spaceId, ref filter);
Update to LibHac 0.13.1 (#2328) Update the LibHac dependency to version 0.13.1. This brings a ton of improvements and changes such as: - Refactor `FsSrv` to match the official refactoring done in FS. - Change how the `Horizon` and `HorizonClient` classes are handled. Each client created represents a different process with its own process ID and client state. - Add FS access control to handle permissions for FS service method calls. - Add FS program registry to keep track of the program ID, location and permissions of each process. - Add FS program index map info manager to track the program IDs and indexes of multi-application programs. - Add all FS IPC interfaces. - Rewrite `Fs.Fsa` code to be more accurate. - Rewrite a lot of `FsSrv` code to be more accurate. - Extend directory save data to store `SaveDataExtraData` - Extend directory save data to lock the save directory to allow only one accessor at a time. - Improve waiting and retrying when encountering access issues in `LocalFileSystem` and `DirectorySaveDataFileSystem`. - More `IFileSystemProxy` methods should work now. - Probably a bunch more stuff. On the Ryujinx side: - Forward most `IFileSystemProxy` methods to LibHac. - Register programs and program index map info when launching an application. - Remove hacks and workarounds for missing LibHac functionality. - Recreate missing save data extra data found on emulator startup. - Create system save data that wasn't indexed correctly on an older LibHac version. `FsSrv` now enforces access control for each process. When a process tries to open a save data file system, FS reads the save's extra data to determine who the save owner is and if the caller has permission to open the save data. Previously-created save data did not have extra data created when the save was created. With access control checks in place, this means that processes with no permissions (most games) wouldn't be able to access their own save data. The extra data can be partially created from data in the save data indexer, which should be enough for access control purposes.
2021-07-13 10:19:28 +02:00
if (result.IsSuccess())
{
MakeObject(context, new ISaveDataInfoReader(infoReader));
}
Update to LibHac 0.13.1 (#2328) Update the LibHac dependency to version 0.13.1. This brings a ton of improvements and changes such as: - Refactor `FsSrv` to match the official refactoring done in FS. - Change how the `Horizon` and `HorizonClient` classes are handled. Each client created represents a different process with its own process ID and client state. - Add FS access control to handle permissions for FS service method calls. - Add FS program registry to keep track of the program ID, location and permissions of each process. - Add FS program index map info manager to track the program IDs and indexes of multi-application programs. - Add all FS IPC interfaces. - Rewrite `Fs.Fsa` code to be more accurate. - Rewrite a lot of `FsSrv` code to be more accurate. - Extend directory save data to store `SaveDataExtraData` - Extend directory save data to lock the save directory to allow only one accessor at a time. - Improve waiting and retrying when encountering access issues in `LocalFileSystem` and `DirectorySaveDataFileSystem`. - More `IFileSystemProxy` methods should work now. - Probably a bunch more stuff. On the Ryujinx side: - Forward most `IFileSystemProxy` methods to LibHac. - Register programs and program index map info when launching an application. - Remove hacks and workarounds for missing LibHac functionality. - Recreate missing save data extra data found on emulator startup. - Create system save data that wasn't indexed correctly on an older LibHac version. `FsSrv` now enforces access control for each process. When a process tries to open a save data file system, FS reads the save's extra data to determine who the save owner is and if the caller has permission to open the save data. Previously-created save data did not have extra data created when the save was created. With access control checks in place, this means that processes with no permissions (most games) wouldn't be able to access their own save data. The extra data can be partially created from data in the save data indexer, which should be enough for access control purposes.
2021-07-13 10:19:28 +02:00
return (ResultCode)result.Value;
}
[CommandHipc(71)]
public ResultCode ReadSaveDataFileSystemExtraDataWithMaskBySaveDataAttribute(ServiceCtx context)
{
Logger.Stub?.PrintStub(LogClass.ServiceFs);
MemoryHelper.FillWithZeros(context.Memory, context.Request.ReceiveBuff[0].Position, (int)context.Request.ReceiveBuff[0].Size);
return ResultCode.Success;
}
[CommandHipc(200)]
// OpenDataStorageByCurrentProcess() -> object<nn::fssrv::sf::IStorage> dataStorage
public ResultCode OpenDataStorageByCurrentProcess(ServiceCtx context)
{
MakeObject(context, new FileSystemProxy.IStorage(context.Device.FileSystem.RomFs.AsStorage()));
return 0;
}
[CommandHipc(202)]
// OpenDataStorageByDataId(u8 storageId, nn::ApplicationId tid) -> object<nn::fssrv::sf::IStorage> dataStorage
public ResultCode OpenDataStorageByDataId(ServiceCtx context)
{
StorageId storageId = (StorageId)context.RequestData.ReadByte();
byte[] padding = context.RequestData.ReadBytes(7);
ulong titleId = context.RequestData.ReadUInt64();
// We do a mitm here to find if the request is for an AOC.
// This is because AOC can be distributed over multiple containers in the emulator.
if (context.Device.System.ContentManager.GetAocDataStorage((ulong)titleId, out LibHac.Fs.IStorage aocStorage, context.Device.Configuration.FsIntegrityCheckLevel))
{
Logger.Info?.Print(LogClass.Loader, $"Opened AddOnContent Data TitleID={titleId:X16}");
MakeObject(context, new FileSystemProxy.IStorage(context.Device.FileSystem.ModLoader.ApplyRomFsMods((ulong)titleId, aocStorage)));
return ResultCode.Success;
}
NcaContentType contentType = NcaContentType.Data;
2018-12-30 14:36:35 +01:00
StorageId installedStorage = context.Device.System.ContentManager.GetInstalledStorage(titleId, contentType, storageId);
if (installedStorage == StorageId.None)
{
contentType = NcaContentType.PublicData;
2018-12-30 14:36:35 +01:00
installedStorage = context.Device.System.ContentManager.GetInstalledStorage(titleId, contentType, storageId);
}
if (installedStorage != StorageId.None)
{
2018-12-30 14:36:35 +01:00
string contentPath = context.Device.System.ContentManager.GetInstalledContentPath(titleId, storageId, contentType);
string installPath = context.Device.FileSystem.SwitchPathToSystemPath(contentPath);
if (!string.IsNullOrWhiteSpace(installPath))
{
string ncaPath = installPath;
if (File.Exists(ncaPath))
{
try
{
LibHac.Fs.IStorage ncaStorage = new LocalStorage(ncaPath, FileAccess.Read, FileMode.Open);
Nca nca = new Nca(context.Device.System.KeySet, ncaStorage);
LibHac.Fs.IStorage romfsStorage = nca.OpenStorage(NcaSectionType.Data, context.Device.System.FsIntegrityCheckLevel);
MakeObject(context, new FileSystemProxy.IStorage(romfsStorage));
}
catch (HorizonResultException ex)
{
return (ResultCode)ex.ResultValue.Value;
}
return ResultCode.Success;
}
else
{
throw new FileNotFoundException($"No Nca found in Path `{ncaPath}`.");
}
}
else
{
throw new DirectoryNotFoundException($"Path for title id {titleId:x16} on Storage {storageId} was not found in Path {installPath}.");
}
}
throw new FileNotFoundException($"System archive with titleid {titleId:x16} was not found on Storage {storageId}. Found in {installedStorage}.");
}
[CommandHipc(203)]
// OpenPatchDataStorageByCurrentProcess() -> object<nn::fssrv::sf::IStorage>
public ResultCode OpenPatchDataStorageByCurrentProcess(ServiceCtx context)
{
MakeObject(context, new FileSystemProxy.IStorage(context.Device.FileSystem.RomFs.AsStorage()));
return ResultCode.Success;
}
[CommandHipc(400)]
// OpenDataStorageByCurrentProcess() -> object<nn::fssrv::sf::IStorage> dataStorage
public ResultCode OpenDeviceOperator(ServiceCtx context)
{
Result result = _baseFileSystemProxy.OpenDeviceOperator(out LibHac.FsSrv.IDeviceOperator deviceOperator);
Update to LibHac 0.13.1 (#2328) Update the LibHac dependency to version 0.13.1. This brings a ton of improvements and changes such as: - Refactor `FsSrv` to match the official refactoring done in FS. - Change how the `Horizon` and `HorizonClient` classes are handled. Each client created represents a different process with its own process ID and client state. - Add FS access control to handle permissions for FS service method calls. - Add FS program registry to keep track of the program ID, location and permissions of each process. - Add FS program index map info manager to track the program IDs and indexes of multi-application programs. - Add all FS IPC interfaces. - Rewrite `Fs.Fsa` code to be more accurate. - Rewrite a lot of `FsSrv` code to be more accurate. - Extend directory save data to store `SaveDataExtraData` - Extend directory save data to lock the save directory to allow only one accessor at a time. - Improve waiting and retrying when encountering access issues in `LocalFileSystem` and `DirectorySaveDataFileSystem`. - More `IFileSystemProxy` methods should work now. - Probably a bunch more stuff. On the Ryujinx side: - Forward most `IFileSystemProxy` methods to LibHac. - Register programs and program index map info when launching an application. - Remove hacks and workarounds for missing LibHac functionality. - Recreate missing save data extra data found on emulator startup. - Create system save data that wasn't indexed correctly on an older LibHac version. `FsSrv` now enforces access control for each process. When a process tries to open a save data file system, FS reads the save's extra data to determine who the save owner is and if the caller has permission to open the save data. Previously-created save data did not have extra data created when the save was created. With access control checks in place, this means that processes with no permissions (most games) wouldn't be able to access their own save data. The extra data can be partially created from data in the save data indexer, which should be enough for access control purposes.
2021-07-13 10:19:28 +02:00
if (result.IsSuccess())
{
MakeObject(context, new IDeviceOperator(deviceOperator));
}
Update to LibHac 0.13.1 (#2328) Update the LibHac dependency to version 0.13.1. This brings a ton of improvements and changes such as: - Refactor `FsSrv` to match the official refactoring done in FS. - Change how the `Horizon` and `HorizonClient` classes are handled. Each client created represents a different process with its own process ID and client state. - Add FS access control to handle permissions for FS service method calls. - Add FS program registry to keep track of the program ID, location and permissions of each process. - Add FS program index map info manager to track the program IDs and indexes of multi-application programs. - Add all FS IPC interfaces. - Rewrite `Fs.Fsa` code to be more accurate. - Rewrite a lot of `FsSrv` code to be more accurate. - Extend directory save data to store `SaveDataExtraData` - Extend directory save data to lock the save directory to allow only one accessor at a time. - Improve waiting and retrying when encountering access issues in `LocalFileSystem` and `DirectorySaveDataFileSystem`. - More `IFileSystemProxy` methods should work now. - Probably a bunch more stuff. On the Ryujinx side: - Forward most `IFileSystemProxy` methods to LibHac. - Register programs and program index map info when launching an application. - Remove hacks and workarounds for missing LibHac functionality. - Recreate missing save data extra data found on emulator startup. - Create system save data that wasn't indexed correctly on an older LibHac version. `FsSrv` now enforces access control for each process. When a process tries to open a save data file system, FS reads the save's extra data to determine who the save owner is and if the caller has permission to open the save data. Previously-created save data did not have extra data created when the save was created. With access control checks in place, this means that processes with no permissions (most games) wouldn't be able to access their own save data. The extra data can be partially created from data in the save data indexer, which should be enough for access control purposes.
2021-07-13 10:19:28 +02:00
return (ResultCode)result.Value;
}
[CommandHipc(630)]
// SetSdCardAccessibility(u8)
public ResultCode SetSdCardAccessibility(ServiceCtx context)
{
bool isAccessible = context.RequestData.ReadBoolean();
return (ResultCode)_baseFileSystemProxy.SetSdCardAccessibility(isAccessible).Value;
}
[CommandHipc(631)]
// IsSdCardAccessible() -> u8
public ResultCode IsSdCardAccessible(ServiceCtx context)
{
Result result = _baseFileSystemProxy.IsSdCardAccessible(out bool isAccessible);
context.ResponseData.Write(isAccessible);
return (ResultCode)result.Value;
Update to LibHac 0.13.1 (#2328) Update the LibHac dependency to version 0.13.1. This brings a ton of improvements and changes such as: - Refactor `FsSrv` to match the official refactoring done in FS. - Change how the `Horizon` and `HorizonClient` classes are handled. Each client created represents a different process with its own process ID and client state. - Add FS access control to handle permissions for FS service method calls. - Add FS program registry to keep track of the program ID, location and permissions of each process. - Add FS program index map info manager to track the program IDs and indexes of multi-application programs. - Add all FS IPC interfaces. - Rewrite `Fs.Fsa` code to be more accurate. - Rewrite a lot of `FsSrv` code to be more accurate. - Extend directory save data to store `SaveDataExtraData` - Extend directory save data to lock the save directory to allow only one accessor at a time. - Improve waiting and retrying when encountering access issues in `LocalFileSystem` and `DirectorySaveDataFileSystem`. - More `IFileSystemProxy` methods should work now. - Probably a bunch more stuff. On the Ryujinx side: - Forward most `IFileSystemProxy` methods to LibHac. - Register programs and program index map info when launching an application. - Remove hacks and workarounds for missing LibHac functionality. - Recreate missing save data extra data found on emulator startup. - Create system save data that wasn't indexed correctly on an older LibHac version. `FsSrv` now enforces access control for each process. When a process tries to open a save data file system, FS reads the save's extra data to determine who the save owner is and if the caller has permission to open the save data. Previously-created save data did not have extra data created when the save was created. With access control checks in place, this means that processes with no permissions (most games) wouldn't be able to access their own save data. The extra data can be partially created from data in the save data indexer, which should be enough for access control purposes.
2021-07-13 10:19:28 +02:00
}
[CommandHipc(1003)]
// DisableAutoSaveDataCreation()
Update to LibHac 0.13.1 (#2328) Update the LibHac dependency to version 0.13.1. This brings a ton of improvements and changes such as: - Refactor `FsSrv` to match the official refactoring done in FS. - Change how the `Horizon` and `HorizonClient` classes are handled. Each client created represents a different process with its own process ID and client state. - Add FS access control to handle permissions for FS service method calls. - Add FS program registry to keep track of the program ID, location and permissions of each process. - Add FS program index map info manager to track the program IDs and indexes of multi-application programs. - Add all FS IPC interfaces. - Rewrite `Fs.Fsa` code to be more accurate. - Rewrite a lot of `FsSrv` code to be more accurate. - Extend directory save data to store `SaveDataExtraData` - Extend directory save data to lock the save directory to allow only one accessor at a time. - Improve waiting and retrying when encountering access issues in `LocalFileSystem` and `DirectorySaveDataFileSystem`. - More `IFileSystemProxy` methods should work now. - Probably a bunch more stuff. On the Ryujinx side: - Forward most `IFileSystemProxy` methods to LibHac. - Register programs and program index map info when launching an application. - Remove hacks and workarounds for missing LibHac functionality. - Recreate missing save data extra data found on emulator startup. - Create system save data that wasn't indexed correctly on an older LibHac version. `FsSrv` now enforces access control for each process. When a process tries to open a save data file system, FS reads the save's extra data to determine who the save owner is and if the caller has permission to open the save data. Previously-created save data did not have extra data created when the save was created. With access control checks in place, this means that processes with no permissions (most games) wouldn't be able to access their own save data. The extra data can be partially created from data in the save data indexer, which should be enough for access control purposes.
2021-07-13 10:19:28 +02:00
public ResultCode DisableAutoSaveDataCreation(ServiceCtx context)
{
// NOTE: This call does nothing in original service.
return ResultCode.Success;
Update to LibHac 0.13.1 (#2328) Update the LibHac dependency to version 0.13.1. This brings a ton of improvements and changes such as: - Refactor `FsSrv` to match the official refactoring done in FS. - Change how the `Horizon` and `HorizonClient` classes are handled. Each client created represents a different process with its own process ID and client state. - Add FS access control to handle permissions for FS service method calls. - Add FS program registry to keep track of the program ID, location and permissions of each process. - Add FS program index map info manager to track the program IDs and indexes of multi-application programs. - Add all FS IPC interfaces. - Rewrite `Fs.Fsa` code to be more accurate. - Rewrite a lot of `FsSrv` code to be more accurate. - Extend directory save data to store `SaveDataExtraData` - Extend directory save data to lock the save directory to allow only one accessor at a time. - Improve waiting and retrying when encountering access issues in `LocalFileSystem` and `DirectorySaveDataFileSystem`. - More `IFileSystemProxy` methods should work now. - Probably a bunch more stuff. On the Ryujinx side: - Forward most `IFileSystemProxy` methods to LibHac. - Register programs and program index map info when launching an application. - Remove hacks and workarounds for missing LibHac functionality. - Recreate missing save data extra data found on emulator startup. - Create system save data that wasn't indexed correctly on an older LibHac version. `FsSrv` now enforces access control for each process. When a process tries to open a save data file system, FS reads the save's extra data to determine who the save owner is and if the caller has permission to open the save data. Previously-created save data did not have extra data created when the save was created. With access control checks in place, this means that processes with no permissions (most games) wouldn't be able to access their own save data. The extra data can be partially created from data in the save data indexer, which should be enough for access control purposes.
2021-07-13 10:19:28 +02:00
}
[CommandHipc(1004)]
// SetGlobalAccessLogMode(u32 mode)
public ResultCode SetGlobalAccessLogMode(ServiceCtx context)
{
int mode = context.RequestData.ReadInt32();
context.Device.System.GlobalAccessLogMode = mode;
return ResultCode.Success;
}
[CommandHipc(1005)]
// GetGlobalAccessLogMode() -> u32 logMode
public ResultCode GetGlobalAccessLogMode(ServiceCtx context)
{
int mode = context.Device.System.GlobalAccessLogMode;
context.ResponseData.Write(mode);
return ResultCode.Success;
}
[CommandHipc(1006)]
// OutputAccessLogToSdCard(buffer<bytes, 5> log_text)
public ResultCode OutputAccessLogToSdCard(ServiceCtx context)
{
string message = ReadUtf8StringSend(context);
// FS ends each line with a newline. Remove it because Ryujinx logging adds its own newline
Logger.AccessLog?.PrintMsg(LogClass.ServiceFs, message.TrimEnd('\n'));
return ResultCode.Success;
}
[CommandHipc(1011)]
public ResultCode GetProgramIndexForAccessLog(ServiceCtx context)
{
int programIndex = 0;
int programCount = 1;
context.ResponseData.Write(programIndex);
context.ResponseData.Write(programCount);
return ResultCode.Success;
}
[CommandHipc(1200)] // 6.0.0+
// OpenMultiCommitManager() -> object<nn::fssrv::sf::IMultiCommitManager>
public ResultCode OpenMultiCommitManager(ServiceCtx context)
{
Result result = _baseFileSystemProxy.OpenMultiCommitManager(out LibHac.FsSrv.IMultiCommitManager commitManager);
if (result.IsSuccess())
{
MakeObject(context, new IMultiCommitManager(commitManager));
}
return (ResultCode)result.Value;
}
}
}