Ryujinx/Ryujinx.HLE/FileSystem/FileSystemProvider.cs

282 lines
7.4 KiB
C#
Raw Normal View History

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
{
2018-12-01 21:01:59 +01:00
private readonly string _basePath;
private readonly string _rootPath;
2018-12-01 21:01:59 +01:00
public FileSystemProvider(string basePath, string rootPath)
{
2018-12-01 21:24:37 +01:00
_basePath = basePath;
_rootPath = rootPath;
2018-12-01 21:01:59 +01:00
CheckIfDescendentOfRootPath(basePath);
}
2018-12-01 21:01:59 +01:00
public long CreateDirectory(string name)
{
2018-12-01 21:01:59 +01:00
CheckIfDescendentOfRootPath(name);
2018-12-01 21:01:59 +01:00
if (Directory.Exists(name))
{
return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists);
}
2018-12-01 21:01:59 +01:00
Directory.CreateDirectory(name);
return 0;
}
2018-12-01 21:01:59 +01:00
public long CreateFile(string name, long size)
{
2018-12-01 21:01:59 +01:00
CheckIfDescendentOfRootPath(name);
2018-12-01 21:01:59 +01:00
if (File.Exists(name))
{
return MakeError(ErrorModule.Fs, FsErr.PathAlreadyExists);
}
2018-12-01 21:01:59 +01:00
using (FileStream newFile = File.Create(name))
{
2018-12-01 21:01:59 +01:00
newFile.SetLength(size);
}
return 0;
}
2018-12-01 21:01:59 +01:00
public long DeleteDirectory(string name, bool recursive)
{
2018-12-01 21:01:59 +01:00
CheckIfDescendentOfRootPath(name);
2018-12-01 21:01:59 +01:00
string dirName = name;
2018-12-01 21:01:59 +01:00
if (!Directory.Exists(dirName))
{
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
}
2018-12-01 21:01:59 +01:00
Directory.Delete(dirName, recursive);
return 0;
}
2018-12-01 21:01:59 +01:00
public long DeleteFile(string name)
{
2018-12-01 21:01:59 +01:00
CheckIfDescendentOfRootPath(name);
2018-12-01 21:01:59 +01:00
if (!File.Exists(name))
{
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
}
else
{
2018-12-01 21:01:59 +01:00
File.Delete(name);
}
return 0;
}
2018-12-01 21:01:59 +01:00
public DirectoryEntry[] GetDirectories(string path)
{
2018-12-01 21:01:59 +01:00
CheckIfDescendentOfRootPath(path);
2018-12-01 21:01:59 +01:00
List<DirectoryEntry> entries = new List<DirectoryEntry>();
2018-12-01 21:01:59 +01:00
foreach(string directory in Directory.EnumerateDirectories(path))
{
2018-12-01 21:01:59 +01:00
DirectoryEntry directoryEntry = new DirectoryEntry(directory, DirectoryEntryType.Directory);
2018-12-01 21:01:59 +01:00
entries.Add(directoryEntry);
}
2018-12-01 21:01:59 +01:00
return entries.ToArray();
}
2018-12-01 21:01:59 +01:00
public DirectoryEntry[] GetEntries(string path)
{
2018-12-01 21:01:59 +01:00
CheckIfDescendentOfRootPath(path);
2018-12-01 21:01:59 +01:00
if (Directory.Exists(path))
{
2018-12-01 21:01:59 +01:00
List<DirectoryEntry> entries = new List<DirectoryEntry>();
2018-12-01 21:01:59 +01:00
foreach (string directory in Directory.EnumerateDirectories(path))
{
2018-12-01 21:01:59 +01:00
DirectoryEntry directoryEntry = new DirectoryEntry(directory, DirectoryEntryType.Directory);
2018-12-01 21:01:59 +01:00
entries.Add(directoryEntry);
}
2018-12-01 21:01:59 +01:00
foreach (string file in Directory.EnumerateFiles(path))
{
2018-12-01 21:01:59 +01:00
FileInfo fileInfo = new FileInfo(file);
DirectoryEntry directoryEntry = new DirectoryEntry(file, DirectoryEntryType.File, fileInfo.Length);
2018-12-01 21:01:59 +01:00
entries.Add(directoryEntry);
}
}
return null;
}
2018-12-01 21:01:59 +01:00
public DirectoryEntry[] GetFiles(string path)
{
2018-12-01 21:01:59 +01:00
CheckIfDescendentOfRootPath(path);
2018-12-01 21:01:59 +01:00
List<DirectoryEntry> entries = new List<DirectoryEntry>();
2018-12-01 21:01:59 +01:00
foreach (string file in Directory.EnumerateFiles(path))
{
2018-12-01 21:01:59 +01:00
FileInfo fileInfo = new FileInfo(file);
DirectoryEntry directoryEntry = new DirectoryEntry(file, DirectoryEntryType.File, fileInfo.Length);
2018-12-01 21:01:59 +01:00
entries.Add(directoryEntry);
}
2018-12-01 21:01:59 +01:00
return entries.ToArray();
}
2018-12-01 21:01:59 +01:00
public long GetFreeSpace(ServiceCtx context)
{
2018-12-01 21:01:59 +01:00
return context.Device.FileSystem.GetDrive().AvailableFreeSpace;
}
2018-12-01 21:01:59 +01:00
public string GetFullPath(string name)
{
2018-12-01 21:01:59 +01:00
if (name.StartsWith("//"))
{
2018-12-01 21:01:59 +01:00
name = name.Substring(2);
}
2018-12-01 21:01:59 +01:00
else if (name.StartsWith('/'))
{
2018-12-01 21:01:59 +01:00
name = name.Substring(1);
}
else
{
return null;
}
2018-12-01 21:01:59 +01:00
string fullPath = Path.Combine(_basePath, name);
2018-12-01 21:01:59 +01:00
CheckIfDescendentOfRootPath(fullPath);
2018-12-01 21:01:59 +01:00
return fullPath;
}
2018-12-01 21:01:59 +01:00
public long GetTotalSpace(ServiceCtx context)
{
2018-12-01 21:01:59 +01:00
return context.Device.FileSystem.GetDrive().TotalSize;
}
2018-12-01 21:01:59 +01:00
public bool DirectoryExists(string name)
{
2018-12-01 21:01:59 +01:00
CheckIfDescendentOfRootPath(name);
2018-12-01 21:01:59 +01:00
return Directory.Exists(name);
}
2018-12-01 21:01:59 +01:00
public bool FileExists(string name)
{
2018-12-01 21:01:59 +01:00
CheckIfDescendentOfRootPath(name);
2018-12-01 21:01:59 +01:00
return File.Exists(name);
}
2018-12-01 21:01:59 +01:00
public long OpenDirectory(string name, int filterFlags, out IDirectory directoryInterface)
{
2018-12-01 21:01:59 +01:00
CheckIfDescendentOfRootPath(name);
2018-12-01 21:01:59 +01:00
if (Directory.Exists(name))
{
2018-12-01 21:01:59 +01:00
directoryInterface = new IDirectory(name, filterFlags, this);
return 0;
}
2018-12-01 21:01:59 +01:00
directoryInterface = null;
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
}
2018-12-01 21:01:59 +01:00
public long OpenFile(string name, out IFile fileInterface)
{
2018-12-01 21:01:59 +01:00
CheckIfDescendentOfRootPath(name);
2018-12-01 21:01:59 +01:00
if (File.Exists(name))
{
2018-12-01 21:01:59 +01:00
FileStream stream = new FileStream(name, FileMode.Open);
2018-12-01 21:01:59 +01:00
fileInterface = new IFile(stream, name);
return 0;
}
2018-12-01 21:01:59 +01:00
fileInterface = null;
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
}
2018-12-01 21:01:59 +01:00
public long RenameDirectory(string oldName, string newName)
{
2018-12-01 21:01:59 +01:00
CheckIfDescendentOfRootPath(oldName);
CheckIfDescendentOfRootPath(newName);
2018-12-01 21:01:59 +01:00
if (Directory.Exists(oldName))
{
2018-12-01 21:01:59 +01:00
Directory.Move(oldName, newName);
}
else
{
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
}
return 0;
}
2018-12-01 21:01:59 +01:00
public long RenameFile(string oldName, string newName)
{
2018-12-01 21:01:59 +01:00
CheckIfDescendentOfRootPath(oldName);
CheckIfDescendentOfRootPath(newName);
2018-12-01 21:01:59 +01:00
if (File.Exists(oldName))
{
2018-12-01 21:01:59 +01:00
File.Move(oldName, newName);
}
else
{
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
}
return 0;
}
2018-12-01 21:01:59 +01:00
public void CheckIfDescendentOfRootPath(string path)
{
2018-12-01 21:01:59 +01:00
DirectoryInfo pathInfo = new DirectoryInfo(path);
DirectoryInfo rootInfo = new DirectoryInfo(_rootPath);
2018-12-01 21:01:59 +01:00
while (pathInfo.Parent != null)
{
2018-12-01 21:01:59 +01:00
if (pathInfo.Parent.FullName == rootInfo.FullName)
{
return;
}
else
{
2018-12-01 21:01:59 +01:00
pathInfo = pathInfo.Parent;
}
}
2018-12-01 21:01:59 +01:00
throw new InvalidOperationException($"Path {path} is not a child directory of {_rootPath}");
}
}
}