Services/AM: Add InstallCIA function for frontends

This commit is contained in:
shinyquagsire23 2017-11-15 12:01:49 -07:00
parent 1f2aa29dee
commit 56e906f1e3
2 changed files with 56 additions and 0 deletions

View File

@ -283,6 +283,49 @@ bool CIAFile::Close() const {
void CIAFile::Flush() const {}
bool InstallCIA(const std::string& path, std::function<ProgressCallback>&& update_callback) {
LOG_INFO(Service_AM, "Installing %s...", path.c_str());
if (!FileUtil::Exists(path)) {
LOG_ERROR(Service_AM, "File %s does not exist!", path.c_str());
return false;
}
FileSys::CIAContainer container;
if (container.Load(path) == Loader::ResultStatus::Success) {
Service::AM::CIAFile installFile(
Service::AM::GetTitleMediaType(container.GetTitleMetadata().GetTitleID()));
FileUtil::IOFile file(path, "rb");
if (!file.IsOpen())
return false;
std::array<u8, 0x10000> buffer;
size_t total_bytes_read = 0;
while (total_bytes_read != file.GetSize()) {
size_t bytes_read = file.ReadBytes(buffer.data(), buffer.size());
auto result = installFile.Write(static_cast<u64>(total_bytes_read), bytes_read, true,
static_cast<u8*>(buffer.data()));
if (update_callback)
update_callback(total_bytes_read, file.GetSize());
if (result.Failed()) {
LOG_ERROR(Service_AM, "CIA file installation aborted with error code %08x",
result.Code());
return false;
}
total_bytes_read += bytes_read;
}
installFile.Close();
LOG_INFO(Service_AM, "Installed %s successfully.", path.c_str());
return true;
}
LOG_ERROR(Service_AM, "CIA file %s is invalid!", path.c_str());
return false;
}
Service::FS::MediaType GetTitleMediaType(u64 titleId) {
u16 platform = static_cast<u16>(titleId >> 48);
u16 category = static_cast<u16>((titleId >> 32) & 0xFFFF);

View File

@ -4,6 +4,7 @@
#pragma once
#include <functional>
#include <string>
#include "common/common_types.h"
#include "core/file_sys/cia_container.h"
@ -41,6 +42,9 @@ enum class CIAInstallState : u32 {
ContentWritten,
};
// Progress callback for InstallCIA, recieves bytes written and total bytes
using ProgressCallback = void(size_t, size_t);
// A file handled returned for CIAs to be written into and subsequently installed.
class CIAFile final : public FileSys::FileBackend {
public:
@ -73,6 +77,15 @@ private:
Service::FS::MediaType media_type;
};
/**
* Installs a CIA file from a specified file path.
* @param path file path of the CIA file to install
* @param update_callback callback function called during filesystem write
* @returns bool whether the install was successful
*/
bool InstallCIA(const std::string& path,
std::function<ProgressCallback>&& update_callback = nullptr);
/**
* Get the mediatype for an installed title
* @param titleId the installed title ID