mirror of
https://github.com/Thealexbarney/LibHac.git
synced 2024-11-14 10:49:41 +01:00
Add EnumerateDeliveryCacheDirectory
This commit is contained in:
parent
1974adb33e
commit
32405fee5f
3 changed files with 140 additions and 2 deletions
|
@ -0,0 +1,99 @@
|
|||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
using LibHac.Common;
|
||||
using LibHac.Fs;
|
||||
|
||||
namespace LibHac.Bcat.Detail.Service.Core
|
||||
{
|
||||
internal class DeliveryCacheDirectoryMetaAccessor
|
||||
{
|
||||
private const int MaxEntryCount = 100;
|
||||
private const int MetaFileHeaderValue = 1;
|
||||
|
||||
private BcatServer Server { get; }
|
||||
private object Locker { get; } = new object();
|
||||
private DeliveryCacheDirectoryMetaEntry[] Entries { get; } = new DeliveryCacheDirectoryMetaEntry[MaxEntryCount];
|
||||
public int Count { get; private set; }
|
||||
|
||||
public DeliveryCacheDirectoryMetaAccessor(BcatServer server)
|
||||
{
|
||||
Server = server;
|
||||
}
|
||||
|
||||
public Result ReadApplicationDirectoryMeta(ulong applicationId, bool allowMissingMetaFile)
|
||||
{
|
||||
Span<byte> metaPath = stackalloc byte[0x50];
|
||||
Server.GetStorageManager().GetDirectoriesMetaPath(metaPath, applicationId);
|
||||
|
||||
return Read(new U8Span(metaPath), allowMissingMetaFile);
|
||||
}
|
||||
|
||||
public Result GetEntry(out DeliveryCacheDirectoryMetaEntry entry, int index)
|
||||
{
|
||||
lock (Locker)
|
||||
{
|
||||
if (index >= Count)
|
||||
{
|
||||
entry = default;
|
||||
return ResultBcat.NotFound.Log();
|
||||
}
|
||||
|
||||
entry = Entries[index];
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
private Result Read(U8Span path, bool allowMissingMetaFile)
|
||||
{
|
||||
lock (Locker)
|
||||
{
|
||||
FileSystemClient fs = Server.GetFsClient();
|
||||
|
||||
Result rc = fs.OpenFile(out FileHandle handle, path, OpenMode.Read);
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
if (ResultFs.PathNotFound.Includes(rc))
|
||||
{
|
||||
if (allowMissingMetaFile)
|
||||
{
|
||||
Count = 0;
|
||||
return Result.Success;
|
||||
}
|
||||
|
||||
return ResultBcat.NotFound.LogConverted(rc);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Count = 0;
|
||||
int header = 0;
|
||||
|
||||
// Verify the header value
|
||||
rc = fs.ReadFile(out long bytesRead, handle, 0, SpanHelpers.AsByteSpan(ref header));
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
if (bytesRead != sizeof(int) || header != MetaFileHeaderValue)
|
||||
return ResultBcat.InvalidDeliveryCacheStorageFile.Log();
|
||||
|
||||
// Read all the directory entries
|
||||
Span<byte> buffer = MemoryMarshal.Cast<DeliveryCacheDirectoryMetaEntry, byte>(Entries);
|
||||
rc = fs.ReadFile(out bytesRead, handle, 4, buffer);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
Count = (int)((uint)bytesRead / Unsafe.SizeOf<DeliveryCacheDirectoryMetaEntry>());
|
||||
|
||||
return Result.Success;
|
||||
}
|
||||
finally
|
||||
{
|
||||
fs.CloseFile(handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,11 @@
|
|||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace LibHac.Bcat.Detail.Service.Core
|
||||
{
|
||||
[StructLayout(LayoutKind.Explicit, Size = 0x40)]
|
||||
internal struct DeliveryCacheDirectoryMetaEntry
|
||||
{
|
||||
[FieldOffset(0x00)] public DirectoryName Name;
|
||||
[FieldOffset(0x20)] public Digest Digest;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,8 @@
|
|||
using System;
|
||||
using System.Diagnostics;
|
||||
using LibHac.Bcat.Detail.Ipc;
|
||||
using LibHac.Bcat.Detail.Service.Core;
|
||||
using LibHac.Common;
|
||||
|
||||
namespace LibHac.Bcat.Detail.Service
|
||||
{
|
||||
|
@ -37,7 +39,7 @@ namespace LibHac.Bcat.Detail.Service
|
|||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public Result CreateDirectoryService(out IDeliveryCacheDirectoryService service)
|
||||
{
|
||||
lock (Locker)
|
||||
|
@ -56,7 +58,33 @@ namespace LibHac.Bcat.Detail.Service
|
|||
|
||||
public Result EnumerateDeliveryCacheDirectory(out int namesRead, Span<DirectoryName> nameBuffer)
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
lock (Locker)
|
||||
{
|
||||
namesRead = default;
|
||||
|
||||
var metaReader = new DeliveryCacheDirectoryMetaAccessor(Server);
|
||||
Result rc = metaReader.ReadApplicationDirectoryMeta(ApplicationId, true);
|
||||
if (rc.IsFailure()) return rc;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < nameBuffer.Length; i++)
|
||||
{
|
||||
rc = metaReader.GetEntry(out DeliveryCacheDirectoryMetaEntry entry, i);
|
||||
|
||||
if (rc.IsFailure())
|
||||
{
|
||||
if (!ResultBcat.NotFound.Includes(rc))
|
||||
return rc;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
StringUtils.Copy(nameBuffer[i].Bytes, entry.Name.Bytes);
|
||||
}
|
||||
|
||||
namesRead = i;
|
||||
return Result.Success;
|
||||
}
|
||||
}
|
||||
|
||||
internal void NotifyCloseFile()
|
||||
|
|
Loading…
Reference in a new issue