Skip to content

Commit

Permalink
Add EnumerateDeliveryCacheDirectory
Browse files Browse the repository at this point in the history
  • Loading branch information
Thealexbarney committed Apr 30, 2020
1 parent 1974adb commit 32405fe
Show file tree
Hide file tree
Showing 3 changed files with 140 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -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);
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -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;
}
}
32 changes: 30 additions & 2 deletions src/LibHac/Bcat/Detail/Service/DeliveryCacheStorageService.cs
Original file line number Diff line number Diff line change
@@ -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
{
Expand Down Expand Up @@ -37,7 +39,7 @@ public Result CreateFileService(out IDeliveryCacheFileService service)
return Result.Success;
}
}

public Result CreateDirectoryService(out IDeliveryCacheDirectoryService service)
{
lock (Locker)
Expand All @@ -56,7 +58,33 @@ public Result CreateDirectoryService(out IDeliveryCacheDirectoryService 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()
Expand Down

0 comments on commit 32405fe

Please sign in to comment.