diff --git a/src/LibHac/Bcat/DeliveryCacheDirectoryEntry.cs b/src/LibHac/Bcat/DeliveryCacheDirectoryEntry.cs index 0996aadb..797027f3 100644 --- a/src/LibHac/Bcat/DeliveryCacheDirectoryEntry.cs +++ b/src/LibHac/Bcat/DeliveryCacheDirectoryEntry.cs @@ -8,5 +8,12 @@ namespace LibHac.Bcat [FieldOffset(0x00)] public FileName Name; [FieldOffset(0x20)] public long Size; [FieldOffset(0x28)] public Digest Digest; + + public DeliveryCacheDirectoryEntry(ref FileName name, long size, ref Digest digest) + { + Name = name; + Size = size; + Digest = digest; + } } } diff --git a/src/LibHac/Bcat/Detail/Ipc/IDeliveryCacheDirectoryService.cs b/src/LibHac/Bcat/Detail/Ipc/IDeliveryCacheDirectoryService.cs index 6a0d9c18..26ff37db 100644 --- a/src/LibHac/Bcat/Detail/Ipc/IDeliveryCacheDirectoryService.cs +++ b/src/LibHac/Bcat/Detail/Ipc/IDeliveryCacheDirectoryService.cs @@ -5,7 +5,7 @@ namespace LibHac.Bcat.Detail.Ipc public interface IDeliveryCacheDirectoryService { Result Open(ref DirectoryName name); - Result Read(ref int entriesRead, Span entryBuffer); - Result GetCount(ref int count); + Result Read(out int entriesRead, Span entryBuffer); + Result GetCount(out int count); } } diff --git a/src/LibHac/Bcat/Detail/Service/Core/DeliveryCacheFileMetaAccessor.cs b/src/LibHac/Bcat/Detail/Service/Core/DeliveryCacheFileMetaAccessor.cs index 78007e7b..da3af499 100644 --- a/src/LibHac/Bcat/Detail/Service/Core/DeliveryCacheFileMetaAccessor.cs +++ b/src/LibHac/Bcat/Detail/Service/Core/DeliveryCacheFileMetaAccessor.cs @@ -14,7 +14,7 @@ namespace LibHac.Bcat.Detail.Service.Core private BcatServer Server { get; } private object Locker { get; } = new object(); private DeliveryCacheFileMetaEntry[] Entries { get; } = new DeliveryCacheFileMetaEntry[MaxEntryCount]; - private int Count { get; set; } + public int Count { get; private set; } public DeliveryCacheFileMetaAccessor(BcatServer server) { @@ -30,6 +30,21 @@ namespace LibHac.Bcat.Detail.Service.Core return Read(new U8Span(metaPath), allowMissingMetaFile); } + public Result GetEntry(out DeliveryCacheFileMetaEntry entry, int index) + { + lock (Locker) + { + if (index >= Count) + { + entry = default; + return ResultBcat.NotFound.Log(); + } + + entry = Entries[index]; + return Result.Success; + } + } + public Result FindEntry(out DeliveryCacheFileMetaEntry entry, ref FileName fileName) { lock (Locker) diff --git a/src/LibHac/Bcat/Detail/Service/DeliveryCacheDirectoryService.cs b/src/LibHac/Bcat/Detail/Service/DeliveryCacheDirectoryService.cs index fc091065..bbeb1a3d 100644 --- a/src/LibHac/Bcat/Detail/Service/DeliveryCacheDirectoryService.cs +++ b/src/LibHac/Bcat/Detail/Service/DeliveryCacheDirectoryService.cs @@ -1,12 +1,13 @@ using System; using LibHac.Bcat.Detail.Ipc; +using LibHac.Bcat.Detail.Service.Core; namespace LibHac.Bcat.Detail.Service { - internal class DeliveryCacheDirectoryService : IDeliveryCacheDirectoryService + internal class DeliveryCacheDirectoryService : IDeliveryCacheDirectoryService, IDisposable { private BcatServer Server { get; } - public object Locker { get; } = new object(); + private object Locker { get; } = new object(); private DeliveryCacheStorageService Parent { get; } private AccessControl Access { get; } private ulong ApplicationId { get; } @@ -25,17 +26,78 @@ namespace LibHac.Bcat.Detail.Service public Result Open(ref DirectoryName name) { - throw new NotImplementedException(); + if (!name.IsValid()) + return ResultBcat.InvalidArgument.Log(); + + lock (Locker) + { + if (IsDirectoryOpen) + return ResultBcat.AlreadyOpen.Log(); + + var metaReader = new DeliveryCacheFileMetaAccessor(Server); + Result rc = metaReader.ReadApplicationFileMeta(ApplicationId, ref name, false); + if (rc.IsFailure()) return rc; + + Count = metaReader.Count; + _name = name; + IsDirectoryOpen = true; + + return Result.Success; + } } - public Result Read(ref int entriesRead, Span entryBuffer) + public Result Read(out int entriesRead, Span entryBuffer) { - throw new NotImplementedException(); + lock (Locker) + { + entriesRead = default; + + if (!IsDirectoryOpen) + return ResultBcat.NotOpen.Log(); + + var metaReader = new DeliveryCacheFileMetaAccessor(Server); + Result rc = metaReader.ReadApplicationFileMeta(ApplicationId, ref _name, true); + if (rc.IsFailure()) return rc; + + int i; + for (i = 0; i < entryBuffer.Length; i++) + { + rc = metaReader.GetEntry(out DeliveryCacheFileMetaEntry entry, i); + + if (rc.IsFailure()) + { + if (!ResultBcat.NotFound.Includes(rc)) + return rc; + + break; + } + + entryBuffer[i] = new DeliveryCacheDirectoryEntry(ref entry.Name, entry.Size, ref entry.Digest); + } + + entriesRead = i; + return Result.Success; + } } - public Result GetCount(ref int count) + public Result GetCount(out int count) { - throw new NotImplementedException(); + lock (Locker) + { + if (!IsDirectoryOpen) + { + count = default; + return ResultBcat.NotOpen.Log(); + } + + count = Count; + return Result.Success; + } + } + + public void Dispose() + { + Parent.NotifyCloseDirectory(); } } }