ncm client: finished InstallTaskBase

This commit is contained in:
Adubbz 2020-03-24 20:12:57 +11:00
parent f70fecfcff
commit cce292e524
6 changed files with 116 additions and 28 deletions

View file

@ -19,12 +19,26 @@
namespace ams::fs {
union RightsId {
u8 data[0x10];
u64 data64[2];
u8 data[0x10];
u64 data64[2];
};
static_assert(sizeof(RightsId) == 0x10);
static_assert(std::is_pod<RightsId>::value);
inline bool operator==(const RightsId &lhs, const RightsId& rhs) {
return std::memcmp(std::addressof(lhs), std::addressof(rhs), sizeof(RightsId)) == 0;
}
inline bool operator!=(const RightsId &lhs, const RightsId &rhs) {
return !(lhs == rhs);
}
inline bool operator<(const RightsId &lhs, const RightsId& rhs) {
return std::memcmp(std::addressof(lhs), std::addressof(rhs), sizeof(RightsId)) < 0;
}
constexpr inline RightsId InvalidRightsId = {};
/* Rights ID API */
Result GetRightsId(RightsId *out, const char *path);
Result GetRightsId(RightsId *out, u8 *out_key_generation, const char *path);

View file

@ -340,13 +340,11 @@ namespace ams::ncm {
void ConvertToContentMeta(void *dst, size_t size, const ContentInfo &meta);
Result CalculateConvertFragmentOnlyInstallContentMetaSize(size_t *out_size, u32 source_version) {
/* TODO */
return ResultSuccess();
AMS_ABORT("Not implemented");
};
Result ConvertToFragmentOnlyInstallContentMeta(void *dst, size_t size, const InstallContentInfo &content_info, u32 source_version) {
/* TODO */
return ResultSuccess();
AMS_ABORT("Not implemented");
}
size_t CountDeltaFragments() const;

View file

@ -19,9 +19,6 @@
namespace ams::ncm {
/* protected:
PrepareContentMeta (both), WritePlaceHolderBuffer, Get/Delete InstallContentMetaData, PrepareDependency, PrepareSystemDependency, PrepareContentMetaIfLatest, GetConfig, WriteContentMetaToPlaceHolder, GetInstallStorage, GetSystemUpdateTaskApplyInfo, CanContinue
*/
enum class ListContentMetaKeyFilter : u8 {
All = 0,
Committed = 1,
@ -91,18 +88,30 @@ PrepareContentMeta (both), WritePlaceHolderBuffer, Get/Delete InstallContentMeta
}
return result;
}
private:
Result PrepareImpl();
Result CleanupOne(const InstallContentMeta &content_meta);
Result ExecuteImpl();
Result CommitImpl(const StorageContentMetaKey *keys, s32 num_keys);
InstallContentInfo MakeInstallContentInfoFrom(const InstallContentMetaInfo &info, const PlaceHolderId &placeholder_id, std::optional<bool> is_temporary);
Result ReadContentMetaInfoList(s32 *out_count, std::unique_ptr<ContentMetaInfo[]> *out_meta_infos, const ContentMetaKey &key);
Result ListRightsIdsByInstallContentMeta(s32 *out_count, Span<RightsId> out_span, const InstallContentMeta &content_meta, s32 offset);
protected:
Result Initialize(StorageId install_storage, InstallTaskDataBase *data, u32 config);
Result CountInstallContentMetaData(s32 *out_count);
Result GetInstallContentMetaData(InstallContentMeta *out_content_meta, s32 index);
Result WritePlaceHolderBuffer(InstallContentInfo *content_info, const void *data, size_t data_size);
Result WriteContentMetaToPlaceHolder(InstallContentInfo *out_install_content_info, ContentStorage *storage, const InstallContentMetaInfo &meta_info, std::optional<bool> is_temporary);
Result PrepareContentMeta(const InstallContentMetaInfo &meta_info, std::optional<ContentMetaKey> key, std::optional<u32> source_version);
Result GetInstallContentMetaDataFromPath(AutoBuffer *out, const Path &path, const InstallContentInfo &content_info, std::optional<u32> source_version);
Result PrepareContentMeta(ContentId content_id, s64 size, ContentMetaType meta_type, AutoBuffer *buffer);
void PrepareAgain();
Result PrepareSystemUpdateDependency();
Result PrepareContentMetaIfLatest(const ContentMetaKey &key);
Result GetSystemUpdateTaskApplyInfo(SystemUpdateTaskApplyInfo *out);
Result DeleteInstallContentMetaData(const ContentMetaKey *keys, s32 num_keys);
Result CanContinue();
public:
/* TODO: Fix access types. */
bool IsCancelRequested();
Result Prepare();
void SetLastResult(Result last_result);
@ -110,14 +119,12 @@ PrepareContentMeta (both), WritePlaceHolderBuffer, Get/Delete InstallContentMeta
Result CalculateRequiredSize(size_t *out_size);
void ResetThroughputMeasurement();
void SetProgressState(InstallProgressState state);
void IncrementProgress(s64 size);
void UpdateThroughputMeasurement(s64 throughput);
bool IsNecessaryInstallTicket(const fs::RightsId &rights_id);
void SetTotalSize(s64 size);
Result PreparePlaceHolder();
Result Cleanup();
Result CleanupOne(const InstallContentMeta &content_meta);
void CleanupProgress();
Result ListContentMetaKey(s32 *out_keys_written, StorageContentMetaKey *out_keys, s32 out_keys_count, s32 offset, ListContentMetaKeyFilter filter);
Result ListApplicationContentMetaKey(s32 *out_keys_written, ApplicationContentMetaKey *out_keys, s32 out_keys_count, s32 offset);
@ -128,32 +135,19 @@ PrepareContentMeta (both), WritePlaceHolderBuffer, Get/Delete InstallContentMeta
Result VerifyAllNotCommitted(const StorageContentMetaKey *keys, s32 num_keys);
Result Commit(const StorageContentMetaKey *keys, s32 num_keys);
Result IncludesExFatDriver(bool *out);
Result WritePlaceHolderBuffer(InstallContentInfo *content_info, const void *data, size_t data_size);
Result WriteContentMetaToPlaceHolder(InstallContentInfo *out_install_content_info, ContentStorage *storage, const InstallContentMetaInfo &meta_info, std::optional<bool> is_temporary);
InstallContentInfo MakeInstallContentInfoFrom(const InstallContentMetaInfo &info, const PlaceHolderId &placeholder_id, std::optional<bool> is_temporary);
Result PrepareContentMeta(const InstallContentMetaInfo &meta_info, std::optional<ContentMetaKey> key, std::optional<u32> source_version);
Result GetInstallContentMetaDataFromPath(AutoBuffer *out, const Path &path, const InstallContentInfo &content_info, std::optional<u32> source_version);
Result PrepareContentMeta(ContentId content_id, s64 size, ContentMetaType meta_type, AutoBuffer *buffer);
Result PrepareSystemUpdateDependency();
Result ReadContentMetaInfoList(s32 *out_count, std::unique_ptr<ContentMetaInfo[]> *out_meta_infos, const ContentMetaKey &key);
Result PrepareContentMetaIfLatest(const ContentMetaKey &key);
Result GetSystemUpdateTaskApplyInfo(SystemUpdateTaskApplyInfo *out);
Result IsNewerThanInstalled(bool *out, const ContentMetaKey &key);
Result DeleteInstallContentMetaData(const ContentMetaKey *keys, s32 num_keys);
void ResetLastResult();
s64 GetThroughput();
Result CalculateContentsSize(s64 *out_size, const ContentMetaKey &key, StorageId storage_id);
Result FindMaxRequiredApplicationVersion(u32 *out);
Result FindMaxRequiredSystemVersion(u32 *out);
Result ListOccupiedSize(s32 *out_written, InstallTaskOccupiedSize *out_list, s32 out_list_size, s32 offset);
Result CanContinue();
void SetFirmwareVariationId(FirmwareVariationId id);
Result ListRightsIds(s32 *out_count, Span<RightsId> out_span, const ContentMetaKey &key, s32 offset);
protected:
virtual Result OnPrepareComplete();
virtual Result PrepareDependency();
public:
/* TODO: Fix access types. */
virtual void Cancel();
virtual void ResetCancel();
virtual InstallProgress GetProgress();

View file

@ -25,4 +25,6 @@ namespace ams::ncm {
u8 reserved[7];
};
static_assert(sizeof(InstallTaskOccupiedSize) == 0x20);
}

View file

@ -27,4 +27,15 @@ namespace ams::ncm {
static_assert(sizeof(RightsId) == 0x18);
static_assert(std::is_pod<RightsId>::value);
inline bool operator==(const RightsId &lhs, const RightsId &rhs) {
return std::tie(lhs.id, lhs.key_generation) == std::tie(rhs.id, rhs.key_generation);
}
inline bool operator!=(const RightsId &lhs, const RightsId &rhs) {
return !(lhs == rhs);
}
inline bool operator<(const RightsId &lhs, const RightsId &rhs) {
return std::tie(lhs.id, lhs.key_generation) < std::tie(rhs.id, rhs.key_generation);
}
}

View file

@ -1305,4 +1305,73 @@ namespace ams::ncm {
void InstallTaskBase::SetFirmwareVariationId(FirmwareVariationId id) {
this->firmware_variation_id = id;
}
Result InstallTaskBase::ListRightsIds(s32 *out_count, Span<RightsId> out_span, const ContentMetaKey &key, s32 offset) {
/* Count the number of content meta entries. */
s32 count;
R_TRY(this->data->Count(std::addressof(count)));
/* Ensure count is >= 1. */
R_UNLESS(count >= 1, ncm::ResultContentMetaNotFound());
/* Iterate over content meta. */
for (s32 i = 0; i < count; i++) {
/* Obtain the content meta. */
InstallContentMeta content_meta;
R_TRY(this->data->Get(std::addressof(content_meta), i));
/* Create a reader. */
const InstallContentMetaReader reader = content_meta.GetReader();
/* List rights ids if the reader's key matches ours. */
if (reader.GetKey() == key) {
return this->ListRightsIdsByInstallContentMeta(out_count, out_span, content_meta, offset);
}
}
return ncm::ResultContentMetaNotFound();
}
Result InstallTaskBase::ListRightsIdsByInstallContentMeta(s32 *out_count, Span<RightsId> out_span, const InstallContentMeta &content_meta, s32 offset) {
/* If the offset is greater than zero, we can't create a unique span of rights ids. */
/* Thus, we have nothing to list. */
if (offset > 0) {
*out_count = 0;
return ResultSuccess();
}
/* Create a reader. */
const InstallContentMetaReader reader = content_meta.GetReader();
s32 count = 0;
for (size_t i = 0; i < reader.GetContentCount(); i++) {
const auto *content_info = reader.GetContentInfo(i);
/* Skip meta content infos and already installed content infos. Also skip if the content meta has already been comitted. */
if (content_info->GetType() == ContentType::Meta || content_info->GetInstallState() == InstallState::Installed || reader.GetHeader()->committed) {
continue;
}
/* Open the relevant content storage. */
ContentStorage content_storage;
R_TRY(ncm::OpenContentStorage(&content_storage, content_info->storage_id));
/* Get the rights id. */
RightsId rights_id;
R_TRY(content_storage.GetRightsId(std::addressof(rights_id), content_info->GetPlaceHolderId()));
/* Skip empty rights ids. */
if (rights_id.id == fs::InvalidRightsId) {
continue;
}
/* Output the rights id. */
out_span[count++] = rights_id;
}
/* Sort and remove duplicate ids from the output span. */
std::sort(out_span.begin(), out_span.end());
*out_count = std::distance(out_span.begin(), std::unique(out_span.begin(), out_span.end()));
return ResultSuccess();
}
}