add support for open fs of internal files

This commit is contained in:
emmaus 2018-11-05 10:06:52 +00:00
parent a6c21db0e3
commit 9c287b211b
7 changed files with 154 additions and 33 deletions

View file

@ -252,5 +252,17 @@ namespace Ryujinx.HLE.FileSystem
throw new InvalidOperationException($"Path {Path} is not a child directory of {RootPath}");
}
public bool Disposed { get; private set; }
protected virtual void Dispose(bool disposing)
{
Disposed = true;
}
public void Dispose()
{
Dispose(true);
}
}
}

View file

@ -1,10 +1,13 @@
using Ryujinx.HLE.HOS;
using Ryujinx.HLE.HOS.Services.FspSrv;
using System;
namespace Ryujinx.HLE.FileSystem
{
interface IFileSystemProvider
interface IFileSystemProvider : IDisposable
{
bool Disposed { get; }
long CreateFile(string Name, long Size);
long CreateDirectory(string Name);

View file

@ -14,6 +14,8 @@ namespace Ryujinx.HLE.FileSystem
{
private Pfs Pfs;
public bool Disposed { get; private set; }
public PFsProvider(Pfs Pfs)
{
this.Pfs = Pfs;
@ -143,5 +145,15 @@ namespace Ryujinx.HLE.FileSystem
{
throw new NotSupportedException();
}
protected virtual void Dispose(bool disposing)
{
}
public void Dispose()
{
Dispose(true);
}
}
}

View file

@ -14,6 +14,8 @@ namespace Ryujinx.HLE.FileSystem
{
private Romfs RomFs;
public bool Disposed { get; private set; }
public RomFsProvider(Stream StorageStream)
{
RomFs = new Romfs(StorageStream);
@ -159,5 +161,15 @@ namespace Ryujinx.HLE.FileSystem
{
throw new NotSupportedException();
}
protected virtual void Dispose(bool disposing)
{
Disposed = true;
}
public void Dispose()
{
Dispose(true);
}
}
}

View file

@ -5,6 +5,7 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
public const int PathDoesNotExist = 1;
public const int PathAlreadyExists = 2;
public const int PathAlreadyInUse = 7;
public const int PartitionNotFound = 1001;
public const int InvalidInput = 6001;
}
}

View file

@ -9,7 +9,7 @@ using static Ryujinx.HLE.Utilities.StringUtils;
namespace Ryujinx.HLE.HOS.Services.FspSrv
{
class IFileSystem : IpcService
class IFileSystem : IpcService, IDisposable
{
private Dictionary<int, ServiceProcessRequest> m_Commands;
@ -386,5 +386,15 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
OpenPaths.Remove(DirInterface.DirectoryPath);
}
}
protected virtual void Dispose(bool disposing)
{
Provider.Dispose();
}
public void Dispose()
{
Dispose(true);
}
}
}

View file

@ -85,6 +85,11 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
if (!File.Exists(FullPath))
{
if (FullPath.Contains("."))
{
return OpenFileSystemFromInternalFile(Context, FullPath);
}
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
}
@ -94,40 +99,11 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
if (Extension == ".nca")
{
Nca Nca = new Nca(Context.Device.System.KeySet, FileStream, false);
NcaSection RomfsSection = Nca.Sections.FirstOrDefault(x => x?.Type == SectionType.Romfs);
if (RomfsSection != null)
{
Stream RomfsStream = Nca.OpenSection(RomfsSection.SectionNum, false, Context.Device.System.FsIntegrityCheckLevel);
IFileSystem NcaFileSystem = new IFileSystem(SwitchPath, new RomFsProvider(RomfsStream));
MakeObject(Context, NcaFileSystem);
return 0;
}
return OpenNcaFs(Context, FullPath, FileStream);
}
else if (Extension == ".nsp")
{
Pfs Nsp = new Pfs(FileStream);
PfsFileEntry TicketFile = Nsp.Files.FirstOrDefault(x => x.Name.EndsWith(".tik"));
if (TicketFile != null)
{
Ticket Ticket = new Ticket(Nsp.OpenFile(TicketFile));
Context.Device.System.KeySet.TitleKeys[Ticket.RightsId] =
Ticket.GetTitleKey(Context.Device.System.KeySet);
}
IFileSystem NspFileSystem = new IFileSystem(SwitchPath, new PFsProvider(Nsp));
MakeObject(Context, NspFileSystem);
return 0;
return OpenNsp(Context, FullPath);
}
return MakeError(ErrorModule.Fs, FsErr.InvalidInput);
@ -264,5 +240,100 @@ namespace Ryujinx.HLE.HOS.Services.FspSrv
MakeObject(Context, new IFileSystem(SavePath, FileSystemProvider));
}
private long OpenNsp(ServiceCtx Context, string PfsPath)
{
FileStream PfsFile = new FileStream(PfsPath, FileMode.Open, FileAccess.Read);
Pfs Nsp = new Pfs(PfsFile);
PfsFileEntry TicketFile = Nsp.Files.FirstOrDefault(x => x.Name.EndsWith(".tik"));
if (TicketFile != null)
{
Ticket Ticket = new Ticket(Nsp.OpenFile(TicketFile));
Context.Device.System.KeySet.TitleKeys[Ticket.RightsId] =
Ticket.GetTitleKey(Context.Device.System.KeySet);
}
IFileSystem NspFileSystem = new IFileSystem(PfsPath, new PFsProvider(Nsp));
MakeObject(Context, NspFileSystem);
return 0;
}
private long OpenNcaFs(ServiceCtx Context,string NcaPath, Stream NcaStream)
{
Nca Nca = new Nca(Context.Device.System.KeySet, NcaStream, false);
NcaSection RomfsSection = Nca.Sections.FirstOrDefault(x => x?.Type == SectionType.Romfs);
NcaSection PfsSection = Nca.Sections.FirstOrDefault(x => x?.Type == SectionType.Pfs0);
if (RomfsSection != null)
{
Stream RomfsStream = Nca.OpenSection(RomfsSection.SectionNum, false, Context.Device.System.FsIntegrityCheckLevel);
IFileSystem NcaFileSystem = new IFileSystem(NcaPath, new RomFsProvider(RomfsStream));
MakeObject(Context, NcaFileSystem);
}
else if(PfsSection !=null)
{
Stream PfsStream = Nca.OpenSection(PfsSection.SectionNum, false, Context.Device.System.FsIntegrityCheckLevel);
Pfs Pfs = new Pfs(PfsStream);
IFileSystem NcaFileSystem = new IFileSystem(NcaPath, new PFsProvider(Pfs));
MakeObject(Context, NcaFileSystem);
}
else
{
return MakeError(ErrorModule.Fs, FsErr.PartitionNotFound);
}
return 0;
}
private long OpenFileSystemFromInternalFile(ServiceCtx Context, string FullPath)
{
DirectoryInfo ArchivePath = new DirectoryInfo(FullPath).Parent;
while (string.IsNullOrWhiteSpace(ArchivePath.Extension))
{
ArchivePath = ArchivePath.Parent;
}
if (ArchivePath.Extension == ".nsp" && File.Exists(ArchivePath.FullName))
{
FileStream PfsFile = new FileStream(
ArchivePath.FullName.TrimEnd(Path.DirectorySeparatorChar),
FileMode.Open,
FileAccess.Read);
Pfs Nsp = new Pfs(PfsFile);
PfsFileEntry TicketFile = Nsp.Files.FirstOrDefault(x => x.Name.EndsWith(".tik"));
if (TicketFile != null)
{
Ticket Ticket = new Ticket(Nsp.OpenFile(TicketFile));
Context.Device.System.KeySet.TitleKeys[Ticket.RightsId] =
Ticket.GetTitleKey(Context.Device.System.KeySet);
}
string Filename = FullPath.Replace(ArchivePath.FullName, string.Empty);
if (Nsp.FileExists(Filename))
{
return OpenNcaFs(Context, FullPath, Nsp.OpenFile(Filename));
}
}
return MakeError(ErrorModule.Fs, FsErr.PathDoesNotExist);
}
}
}