diff options
| author | gdkchan <gab.dark.100@gmail.com> | 2018-02-21 18:56:52 -0300 |
|---|---|---|
| committer | gdkchan <gab.dark.100@gmail.com> | 2018-02-21 18:56:52 -0300 |
| commit | b2f733da7839ff8ba7a70a529cb9eb3eea9f0af6 (patch) | |
| tree | 2ed5913d93ecf3deeabfe706934b57ee6f2309b6 /Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs | |
| parent | 3696255457dce06111ce5a07544d30239366ebf6 (diff) | |
FspSrv improvements, also fix ImageEnd for NROs without a MOD0 section
Diffstat (limited to 'Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs')
| -rw-r--r-- | Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs | 309 |
1 files changed, 218 insertions, 91 deletions
diff --git a/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs b/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs index 68b15845..e18c1daf 100644 --- a/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs +++ b/Ryujinx.Core/OsHle/Objects/FspSrv/IFileSystem.cs @@ -1,8 +1,10 @@ using ChocolArm64.Memory; using Ryujinx.Core.OsHle.Ipc; +using System; using System.Collections.Generic; using System.IO; +using static Ryujinx.Core.OsHle.Objects.ErrorCode; using static Ryujinx.Core.OsHle.Objects.ObjHelper; namespace Ryujinx.Core.OsHle.Objects.FspSrv @@ -13,153 +15,214 @@ namespace Ryujinx.Core.OsHle.Objects.FspSrv public IReadOnlyDictionary<int, ServiceProcessRequest> Commands => m_Commands; + private HashSet<string> OpenPaths; + private string Path; public IFileSystem(string Path) { - //TODO: implement. m_Commands = new Dictionary<int, ServiceProcessRequest>() { - { 0, CreateFile }, - { 1, DeleteFile }, - { 2, CreateDirectory }, - { 3, DeleteDirectory }, + { 0, CreateFile }, + { 1, DeleteFile }, + { 2, CreateDirectory }, + { 3, DeleteDirectory }, { 4, DeleteDirectoryRecursively }, - { 5, RenameFile }, - { 6, RenameDirectory }, - { 7, GetEntryType }, - { 8, OpenFile }, - { 9, OpenDirectory }, - { 10, Commit }, - //{ 11, GetFreeSpaceSize }, - //{ 12, GetTotalSpaceSize }, - //{ 13, CleanDirectoryRecursively }, - //{ 14, GetFileTimeStampRaw } + { 5, RenameFile }, + { 6, RenameDirectory }, + { 7, GetEntryType }, + { 8, OpenFile }, + { 9, OpenDirectory }, + { 10, Commit }, + { 11, GetFreeSpaceSize }, + { 12, GetTotalSpaceSize }, + //{ 13, CleanDirectoryRecursively }, + //{ 14, GetFileTimeStampRaw } }; + OpenPaths = new HashSet<string>(); + this.Path = Path; } public long CreateFile(ServiceCtx Context) { long Position = Context.Request.PtrBuff[0].Position; + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); - ulong Mode = Context.RequestData.ReadUInt64(); - uint Size = Context.RequestData.ReadUInt32(); + + long Mode = Context.RequestData.ReadInt64(); + int Size = Context.RequestData.ReadInt32(); + string FileName = Context.Ns.VFs.GetFullPath(Path, Name); - if (FileName != null) + if (FileName == null) + { + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } + + if (File.Exists(FileName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists); + } + + if (IsPathAlreadyInUse(FileName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); + } + + using (FileStream NewFile = File.Create(FileName)) { - FileStream NewFile = File.Create(FileName); NewFile.SetLength(Size); - NewFile.Close(); - return 0; } - //TODO: Correct error code. - return -1; + return 0; } public long DeleteFile(ServiceCtx Context) { long Position = Context.Request.PtrBuff[0].Position; + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + string FileName = Context.Ns.VFs.GetFullPath(Path, Name); - if (FileName != null) + if (!File.Exists(FileName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } + + if (IsPathAlreadyInUse(FileName)) { - File.Delete(FileName); - return 0; + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); } - //TODO: Correct error code. - return -1; + File.Delete(FileName); + + return 0; } public long CreateDirectory(ServiceCtx Context) { long Position = Context.Request.PtrBuff[0].Position; + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); - string FileName = Context.Ns.VFs.GetFullPath(Path, Name); - if (FileName != null) + string DirName = Context.Ns.VFs.GetFullPath(Path, Name); + + if (DirName == null) { - Directory.CreateDirectory(FileName); - return 0; + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); } - //TODO: Correct error code. - return -1; - } - - public long DeleteDirectory(ServiceCtx Context) - { - long Position = Context.Request.PtrBuff[0].Position; - string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); - string FileName = Context.Ns.VFs.GetFullPath(Path, Name); + if (Directory.Exists(DirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists); + } - if (FileName != null) + if (IsPathAlreadyInUse(DirName)) { - Directory.Delete(FileName); - return 0; + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); } - // TODO: Correct error code. - return -1; + Directory.CreateDirectory(DirName); + + return 0; + } + + public long DeleteDirectory(ServiceCtx Context) + { + return DeleteDirectory(Context, false); } public long DeleteDirectoryRecursively(ServiceCtx Context) { + return DeleteDirectory(Context, true); + } + + private long DeleteDirectory(ServiceCtx Context, bool Recursive) + { long Position = Context.Request.PtrBuff[0].Position; + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); - string FileName = Context.Ns.VFs.GetFullPath(Path, Name); - if (FileName != null) + string DirName = Context.Ns.VFs.GetFullPath(Path, Name); + + if (!Directory.Exists(DirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } + + if (IsPathAlreadyInUse(DirName)) { - Directory.Delete(FileName, true); // recursive = true - return 0; + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); } - // TODO: Correct error code. - return -1; + Directory.Delete(DirName, Recursive); + + return 0; } public long RenameFile(ServiceCtx Context) { long OldPosition = Context.Request.PtrBuff[0].Position; long NewPosition = Context.Request.PtrBuff[0].Position; + string OldName = AMemoryHelper.ReadAsciiString(Context.Memory, OldPosition); string NewName = AMemoryHelper.ReadAsciiString(Context.Memory, NewPosition); + string OldFileName = Context.Ns.VFs.GetFullPath(Path, OldName); string NewFileName = Context.Ns.VFs.GetFullPath(Path, NewName); - if (OldFileName != null && NewFileName != null) + if (!File.Exists(OldFileName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } + + if (File.Exists(NewFileName)) { - File.Move(OldFileName, NewFileName); - return 0; + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists); } - // TODO: Correct error code. - return -1; + if (IsPathAlreadyInUse(OldFileName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); + } + + File.Move(OldFileName, NewFileName); + + return 0; } public long RenameDirectory(ServiceCtx Context) { long OldPosition = Context.Request.PtrBuff[0].Position; long NewPosition = Context.Request.PtrBuff[0].Position; + string OldName = AMemoryHelper.ReadAsciiString(Context.Memory, OldPosition); string NewName = AMemoryHelper.ReadAsciiString(Context.Memory, NewPosition); + string OldDirName = Context.Ns.VFs.GetFullPath(Path, OldName); string NewDirName = Context.Ns.VFs.GetFullPath(Path, NewName); - if (OldDirName != null && NewDirName != null) + if (!Directory.Exists(OldDirName)) { - Directory.Move(OldDirName, NewDirName); - return 0; + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); } - // TODO: Correct error code. - return -1; + if (Directory.Exists(NewDirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists); + } + + if (IsPathAlreadyInUse(OldDirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); + } + + Directory.Move(OldDirName, NewDirName); + + return 0; } public long GetEntryType(ServiceCtx Context) @@ -170,15 +233,20 @@ namespace Ryujinx.Core.OsHle.Objects.FspSrv string FileName = Context.Ns.VFs.GetFullPath(Path, Name); - if (FileName == null) + if (File.Exists(FileName)) { - //TODO: Correct error code. - return -1; + Context.ResponseData.Write(1); } + else if (Directory.Exists(FileName)) + { + Context.ResponseData.Write(0); + } + else + { + Context.ResponseData.Write(0); - bool IsFile = File.Exists(FileName); - - Context.ResponseData.Write(IsFile ? 1 : 0); + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } return 0; } @@ -193,22 +261,21 @@ namespace Ryujinx.Core.OsHle.Objects.FspSrv string FileName = Context.Ns.VFs.GetFullPath(Path, Name); - if (FileName == null) + if (!File.Exists(FileName)) { - //TODO: Correct error code. - return -1; + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); } - if (File.Exists(FileName)) + if (IsPathAlreadyInUse(FileName)) { - FileStream Stream = new FileStream(FileName, FileMode.OpenOrCreate); - MakeObject(Context, new IFile(Stream)); - - return 0; + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); } - //TODO: Correct error code. - return -1; + FileStream Stream = new FileStream(FileName, FileMode.Open); + + MakeObject(Context, new IFile(Stream, FileName)); + + return 0; } public long OpenDirectory(ServiceCtx Context) @@ -221,27 +288,87 @@ namespace Ryujinx.Core.OsHle.Objects.FspSrv string DirName = Context.Ns.VFs.GetFullPath(Path, Name); - if(DirName != null) + if (!Directory.Exists(DirName)) { - if (Directory.Exists(DirName)) - { - MakeObject(Context, new IDirectory(DirName, FilterFlags)); - return 0; - } - else - { - // TODO: correct error code. - return -1; - } + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); } - // TODO: Correct error code. - return -1; + if (IsPathAlreadyInUse(DirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyInUse); + } + + IDirectory DirInterface = new IDirectory(DirName, FilterFlags); + + DirInterface.Disposed += RemoveDirectoryInUse; + + lock (OpenPaths) + { + OpenPaths.Add(DirName); + } + + MakeObject(Context, DirInterface); + + return 0; } public long Commit(ServiceCtx Context) { return 0; } + + public long GetFreeSpaceSize(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + + Context.ResponseData.Write(Context.Ns.VFs.GetDrive().AvailableFreeSpace); + + return 0; + } + + public long GetTotalSpaceSize(ServiceCtx Context) + { + long Position = Context.Request.PtrBuff[0].Position; + + string Name = AMemoryHelper.ReadAsciiString(Context.Memory, Position); + + Context.ResponseData.Write(Context.Ns.VFs.GetDrive().TotalSize); + + return 0; + } + + private bool IsPathAlreadyInUse(string Path) + { + lock (OpenPaths) + { + return OpenPaths.Contains(Path); + } + } + + private void RemoveFileInUse(object sender, EventArgs e) + { + IFile FileInterface = (IFile)sender; + + lock (OpenPaths) + { + FileInterface.Disposed -= RemoveDirectoryInUse; + + OpenPaths.Remove(FileInterface.HostPath); + } + } + + private void RemoveDirectoryInUse(object sender, EventArgs e) + { + IDirectory DirInterface = (IDirectory)sender; + + lock (OpenPaths) + { + DirInterface.Disposed -= RemoveDirectoryInUse; + + OpenPaths.Remove(DirInterface.HostPath); + } + } } }
\ No newline at end of file |
