IOS/ES: Implement GetSharedContents (+ count)

Used by the system menu when importing a title from SD.

These are probably the last two ioctlvs used by a major title.
This commit is contained in:
Léo Lam 2017-04-06 14:14:40 +02:00
parent 1035a8b697
commit b09561ece2
7 changed files with 68 additions and 0 deletions

View File

@ -356,6 +356,11 @@ IPCCommandResult ES::IOCtlV(const IOCtlVRequest& request)
case IOCTL_ES_GETSTOREDCONTENTS: case IOCTL_ES_GETSTOREDCONTENTS:
return GetTMDStoredContents(request); return GetTMDStoredContents(request);
case IOCTL_ES_GETSHAREDCONTENTCNT:
return GetSharedContentsCount(request);
case IOCTL_ES_GETSHAREDCONTENTS:
return GetSharedContents(request);
case IOCTL_ES_GETVIEWCNT: case IOCTL_ES_GETVIEWCNT:
return GetTicketViewCount(request); return GetTicketViewCount(request);
case IOCTL_ES_GETVIEWS: case IOCTL_ES_GETVIEWS:

View File

@ -214,6 +214,8 @@ private:
IPCCommandResult GetTMDStoredContents(const IOCtlVRequest& request); IPCCommandResult GetTMDStoredContents(const IOCtlVRequest& request);
IPCCommandResult GetStoredTMDSize(const IOCtlVRequest& request); IPCCommandResult GetStoredTMDSize(const IOCtlVRequest& request);
IPCCommandResult GetStoredTMD(const IOCtlVRequest& request); IPCCommandResult GetStoredTMD(const IOCtlVRequest& request);
IPCCommandResult GetSharedContentsCount(const IOCtlVRequest& request) const;
IPCCommandResult GetSharedContents(const IOCtlVRequest& request) const;
// Views for tickets and TMDs // Views for tickets and TMDs
IPCCommandResult GetTicketViewCount(const IOCtlVRequest& request); IPCCommandResult GetTicketViewCount(const IOCtlVRequest& request);

View File

@ -385,6 +385,16 @@ std::string SharedContentMap::GetFilenameFromSHA1(const std::array<u8, 20>& sha1
return Common::RootUserPath(m_root) + StringFromFormat("/shared1/%s.app", id_string.c_str()); return Common::RootUserPath(m_root) + StringFromFormat("/shared1/%s.app", id_string.c_str());
} }
std::vector<std::array<u8, 20>> SharedContentMap::GetHashes() const
{
std::vector<std::array<u8, 20>> hashes;
hashes.reserve(m_entries.size());
for (const auto& content_entry : m_entries)
hashes.emplace_back(content_entry.sha1);
return hashes;
}
std::string SharedContentMap::AddSharedContent(const std::array<u8, 20>& sha1) std::string SharedContentMap::AddSharedContent(const std::array<u8, 20>& sha1)
{ {
std::string filename = GetFilenameFromSHA1(sha1); std::string filename = GetFilenameFromSHA1(sha1);

View File

@ -204,6 +204,7 @@ public:
std::string GetFilenameFromSHA1(const std::array<u8, 20>& sha1) const; std::string GetFilenameFromSHA1(const std::array<u8, 20>& sha1) const;
std::string AddSharedContent(const std::array<u8, 20>& sha1); std::string AddSharedContent(const std::array<u8, 20>& sha1);
std::vector<std::array<u8, 20>> GetHashes() const;
private: private:
struct Entry; struct Entry;

View File

@ -163,6 +163,23 @@ std::vector<Content> GetStoredContentsFromTMD(const TMDReader& tmd)
return stored_contents; return stored_contents;
} }
u32 GetSharedContentsCount()
{
const std::string shared1_path = Common::RootUserPath(Common::FROM_SESSION_ROOT) + "/shared1";
const auto entries = File::ScanDirectoryTree(shared1_path, false);
return static_cast<u32>(
std::count_if(entries.children.begin(), entries.children.end(), [](const auto& entry) {
return !entry.isDirectory && entry.virtualName.size() == 12 &&
entry.virtualName.compare(8, 4, ".app") == 0;
}));
}
std::vector<std::array<u8, 20>> GetSharedContents()
{
const IOS::ES::SharedContentMap map{Common::FROM_SESSION_ROOT};
return map.GetHashes();
}
bool InitImport(u64 title_id) bool InitImport(u64 title_id)
{ {
const std::string content_dir = Common::GetTitleContentPath(title_id, Common::FROM_SESSION_ROOT); const std::string content_dir = Common::GetTitleContentPath(title_id, Common::FROM_SESSION_ROOT);

View File

@ -4,6 +4,7 @@
#pragma once #pragma once
#include <array>
#include <vector> #include <vector>
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
@ -27,6 +28,9 @@ std::vector<u64> GetTitlesWithTickets();
std::vector<Content> GetStoredContentsFromTMD(const TMDReader& tmd); std::vector<Content> GetStoredContentsFromTMD(const TMDReader& tmd);
u32 GetSharedContentsCount();
std::vector<std::array<u8, 20>> GetSharedContents();
// Start a title import. // Start a title import.
bool InitImport(u64 title_id); bool InitImport(u64 title_id);
// Clean up the import content directory and move it back to /title. // Clean up the import content directory and move it back to /title.

View File

@ -205,6 +205,35 @@ IPCCommandResult ES::GetBoot2Version(const IOCtlVRequest& request)
Memory::Write_U32(4, request.io_vectors[0].address); Memory::Write_U32(4, request.io_vectors[0].address);
return GetDefaultReply(IPC_SUCCESS); return GetDefaultReply(IPC_SUCCESS);
} }
IPCCommandResult ES::GetSharedContentsCount(const IOCtlVRequest& request) const
{
if (!request.HasNumberOfValidVectors(0, 1) || request.io_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
const u32 count = IOS::ES::GetSharedContentsCount();
Memory::Write_U32(count, request.io_vectors[0].address);
INFO_LOG(IOS_ES, "GetSharedContentsCount: %u contents", count);
return GetDefaultReply(IPC_SUCCESS);
}
IPCCommandResult ES::GetSharedContents(const IOCtlVRequest& request) const
{
if (!request.HasNumberOfValidVectors(1, 1) || request.in_vectors[0].size != sizeof(u32))
return GetDefaultReply(ES_EINVAL);
const u32 max_count = Memory::Read_U32(request.in_vectors[0].address);
if (request.io_vectors[0].size != 20 * max_count)
return GetDefaultReply(ES_EINVAL);
const std::vector<std::array<u8, 20>> hashes = IOS::ES::GetSharedContents();
const u32 count = std::min(static_cast<u32>(hashes.size()), max_count);
Memory::CopyToEmu(request.io_vectors[0].address, hashes.data(), 20 * count);
INFO_LOG(IOS_ES, "GetSharedContents: %u contents (%u requested)", count, max_count);
return GetDefaultReply(IPC_SUCCESS);
}
} // namespace Device } // namespace Device
} // namespace HLE } // namespace HLE
} // namespace IOS } // namespace IOS