diff options
Diffstat (limited to 'Ryujinx.HLE/FileSystem/FileSystemProvider.cs')
-rw-r--r-- | Ryujinx.HLE/FileSystem/FileSystemProvider.cs | 281 |
1 files changed, 281 insertions, 0 deletions
diff --git a/Ryujinx.HLE/FileSystem/FileSystemProvider.cs b/Ryujinx.HLE/FileSystem/FileSystemProvider.cs new file mode 100644 index 00000000..37ccfb10 --- /dev/null +++ b/Ryujinx.HLE/FileSystem/FileSystemProvider.cs @@ -0,0 +1,281 @@ +using Ryujinx.HLE.HOS; +using Ryujinx.HLE.HOS.Services.FspSrv; +using System; +using System.Collections.Generic; +using System.IO; + +using static Ryujinx.HLE.HOS.ErrorCode; + +namespace Ryujinx.HLE.FileSystem +{ + class FileSystemProvider : IFileSystemProvider + { + private readonly string BasePath; + private readonly string RootPath; + + public FileSystemProvider(string BasePath, string RootPath) + { + this.BasePath = BasePath; + this.RootPath = RootPath; + + CheckIfDecendentOfRootPath(BasePath); + } + + public long CreateDirectory(string Name) + { + CheckIfDecendentOfRootPath(Name); + + if (Directory.Exists(Name)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists); + } + + Directory.CreateDirectory(Name); + + return 0; + } + + public long CreateFile(string Name, long Size) + { + CheckIfDecendentOfRootPath(Name); + + if (File.Exists(Name)) + { + return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists); + } + + using (FileStream NewFile = File.Create(Name)) + { + NewFile.SetLength(Size); + } + + return 0; + } + + public long DeleteDirectory(string Name, bool Recursive) + { + CheckIfDecendentOfRootPath(Name); + + string DirName = Name; + + if (!Directory.Exists(DirName)) + { + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } + + Directory.Delete(DirName, Recursive); + + return 0; + } + + public long DeleteFile(string Name) + { + CheckIfDecendentOfRootPath(Name); + + if (!File.Exists(Name)) + { + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } + else + { + File.Delete(Name); + } + + return 0; + } + + public DirectoryEntry[] GetDirectories(string Path) + { + CheckIfDecendentOfRootPath(Path); + + List<DirectoryEntry> Entries = new List<DirectoryEntry>(); + + foreach(string Directory in Directory.EnumerateDirectories(Path)) + { + DirectoryEntry DirectoryEntry = new DirectoryEntry(Directory, DirectoryEntryType.Directory); + + Entries.Add(DirectoryEntry); + } + + return Entries.ToArray(); + } + + public DirectoryEntry[] GetEntries(string Path) + { + CheckIfDecendentOfRootPath(Path); + + if (Directory.Exists(Path)) + { + List<DirectoryEntry> Entries = new List<DirectoryEntry>(); + + foreach (string Directory in Directory.EnumerateDirectories(Path)) + { + DirectoryEntry DirectoryEntry = new DirectoryEntry(Directory, DirectoryEntryType.Directory); + + Entries.Add(DirectoryEntry); + } + + foreach (string File in Directory.EnumerateFiles(Path)) + { + FileInfo FileInfo = new FileInfo(File); + DirectoryEntry DirectoryEntry = new DirectoryEntry(File, DirectoryEntryType.File, FileInfo.Length); + + Entries.Add(DirectoryEntry); + } + } + + return null; + } + + public DirectoryEntry[] GetFiles(string Path) + { + CheckIfDecendentOfRootPath(Path); + + List<DirectoryEntry> Entries = new List<DirectoryEntry>(); + + foreach (string File in Directory.EnumerateFiles(Path)) + { + FileInfo FileInfo = new FileInfo(File); + DirectoryEntry DirectoryEntry = new DirectoryEntry(File, DirectoryEntryType.File, FileInfo.Length); + + Entries.Add(DirectoryEntry); + } + + return Entries.ToArray(); + } + + public long GetFreeSpace(ServiceCtx Context) + { + return Context.Device.FileSystem.GetDrive().AvailableFreeSpace; + } + + public string GetFullPath(string Name) + { + if (Name.StartsWith("//")) + { + Name = Name.Substring(2); + } + else if (Name.StartsWith('/')) + { + Name = Name.Substring(1); + } + else + { + return null; + } + + string FullPath = Path.Combine(BasePath, Name); + + CheckIfDecendentOfRootPath(FullPath); + + return FullPath; + } + + public long GetTotalSpace(ServiceCtx Context) + { + return Context.Device.FileSystem.GetDrive().TotalSize; + } + + public bool DirectoryExists(string Name) + { + CheckIfDecendentOfRootPath(Name); + + return Directory.Exists(Name); + } + + public bool FileExists(string Name) + { + CheckIfDecendentOfRootPath(Name); + + return File.Exists(Name); + } + + public long OpenDirectory(string Name, int FilterFlags, out IDirectory DirectoryInterface) + { + CheckIfDecendentOfRootPath(Name); + + if (Directory.Exists(Name)) + { + DirectoryInterface = new IDirectory(Name, FilterFlags, this); + + return 0; + } + + DirectoryInterface = null; + + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } + + public long OpenFile(string Name, out IFile FileInterface) + { + CheckIfDecendentOfRootPath(Name); + + if (File.Exists(Name)) + { + FileStream Stream = new FileStream(Name, FileMode.Open); + + FileInterface = new IFile(Stream, Name); + + return 0; + } + + FileInterface = null; + + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } + + public long RenameDirectory(string OldName, string NewName) + { + CheckIfDecendentOfRootPath(OldName); + CheckIfDecendentOfRootPath(NewName); + + if (Directory.Exists(OldName)) + { + Directory.Move(OldName, NewName); + } + else + { + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } + + return 0; + } + + public long RenameFile(string OldName, string NewName) + { + CheckIfDecendentOfRootPath(OldName); + CheckIfDecendentOfRootPath(NewName); + + if (File.Exists(OldName)) + { + File.Move(OldName, NewName); + } + else + { + return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist); + } + + return 0; + } + + public void CheckIfDecendentOfRootPath(string Path) + { + DirectoryInfo PathInfo = new DirectoryInfo(Path); + DirectoryInfo RootInfo = new DirectoryInfo(RootPath); + + while (PathInfo.Parent != null) + { + if (PathInfo.Parent.FullName == RootInfo.FullName) + { + return; + } + else + { + PathInfo = PathInfo.Parent; + } + } + + throw new InvalidOperationException($"Path {Path} is not a child directory of {RootPath}"); + } + } +} |