am: Resolve truncation and sign conversion warnings in WriteContentData() (#5397)
We can adjust the API to allow std::size_t indices, which simplifies operating with standard container types. It also prevents truncation warnings from occurring in these cases as well.
This commit is contained in:
parent
353780e1c9
commit
902cc1eb49
|
@ -206,10 +206,10 @@ u64 CIAContainer::GetMetadataOffset() const {
|
||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 CIAContainer::GetContentOffset(u16 index) const {
|
u64 CIAContainer::GetContentOffset(std::size_t index) const {
|
||||||
u64 offset =
|
u64 offset =
|
||||||
Common::AlignUp(GetTitleMetadataOffset() + cia_header.tmd_size, CIA_SECTION_ALIGNMENT);
|
Common::AlignUp(GetTitleMetadataOffset() + cia_header.tmd_size, CIA_SECTION_ALIGNMENT);
|
||||||
for (u16 i = 0; i < index; i++) {
|
for (std::size_t i = 0; i < index; i++) {
|
||||||
offset += GetContentSize(i);
|
offset += GetContentSize(i);
|
||||||
}
|
}
|
||||||
return offset;
|
return offset;
|
||||||
|
@ -235,10 +235,11 @@ u64 CIAContainer::GetTotalContentSize() const {
|
||||||
return cia_header.content_size;
|
return cia_header.content_size;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 CIAContainer::GetContentSize(u16 index) const {
|
u64 CIAContainer::GetContentSize(std::size_t index) const {
|
||||||
// If the content doesn't exist in the CIA, it doesn't have a size.
|
// If the content doesn't exist in the CIA, it doesn't have a size.
|
||||||
if (!cia_header.isContentPresent(index))
|
if (!cia_header.IsContentPresent(index)) {
|
||||||
return 0;
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
return cia_tmd.GetContentSizeByIndex(index);
|
return cia_tmd.GetContentSizeByIndex(index);
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,14 +58,14 @@ public:
|
||||||
u64 GetTicketOffset() const;
|
u64 GetTicketOffset() const;
|
||||||
u64 GetTitleMetadataOffset() const;
|
u64 GetTitleMetadataOffset() const;
|
||||||
u64 GetMetadataOffset() const;
|
u64 GetMetadataOffset() const;
|
||||||
u64 GetContentOffset(u16 index = 0) const;
|
u64 GetContentOffset(std::size_t index = 0) const;
|
||||||
|
|
||||||
u32 GetCertificateSize() const;
|
u32 GetCertificateSize() const;
|
||||||
u32 GetTicketSize() const;
|
u32 GetTicketSize() const;
|
||||||
u32 GetTitleMetadataSize() const;
|
u32 GetTitleMetadataSize() const;
|
||||||
u32 GetMetadataSize() const;
|
u32 GetMetadataSize() const;
|
||||||
u64 GetTotalContentSize() const;
|
u64 GetTotalContentSize() const;
|
||||||
u64 GetContentSize(u16 index = 0) const;
|
u64 GetContentSize(std::size_t index = 0) const;
|
||||||
|
|
||||||
void Print() const;
|
void Print() const;
|
||||||
|
|
||||||
|
@ -81,11 +81,11 @@ private:
|
||||||
u64_le content_size;
|
u64_le content_size;
|
||||||
std::array<u8, CIA_CONTENT_BITS_SIZE> content_present;
|
std::array<u8, CIA_CONTENT_BITS_SIZE> content_present;
|
||||||
|
|
||||||
bool isContentPresent(u16 index) const {
|
bool IsContentPresent(std::size_t index) const {
|
||||||
// The content_present is a bit array which defines which content in the TMD
|
// The content_present is a bit array which defines which content in the TMD
|
||||||
// is included in the CIA, so check the bit for this index and add if set.
|
// is included in the CIA, so check the bit for this index and add if set.
|
||||||
// The bits in the content index are arranged w/ index 0 as the MSB, 7 as the LSB, etc.
|
// The bits in the content index are arranged w/ index 0 as the MSB, 7 as the LSB, etc.
|
||||||
return (content_present[index >> 3] & (0x80 >> (index & 7)));
|
return (content_present[index >> 3] & (0x80 >> (index & 7))) != 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -165,19 +165,19 @@ u32 TitleMetadata::GetDLPContentID() const {
|
||||||
return tmd_chunks[TMDContentIndex::DLP].id;
|
return tmd_chunks[TMDContentIndex::DLP].id;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 TitleMetadata::GetContentIDByIndex(u16 index) const {
|
u32 TitleMetadata::GetContentIDByIndex(std::size_t index) const {
|
||||||
return tmd_chunks[index].id;
|
return tmd_chunks[index].id;
|
||||||
}
|
}
|
||||||
|
|
||||||
u16 TitleMetadata::GetContentTypeByIndex(u16 index) const {
|
u16 TitleMetadata::GetContentTypeByIndex(std::size_t index) const {
|
||||||
return tmd_chunks[index].type;
|
return tmd_chunks[index].type;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 TitleMetadata::GetContentSizeByIndex(u16 index) const {
|
u64 TitleMetadata::GetContentSizeByIndex(std::size_t index) const {
|
||||||
return tmd_chunks[index].size;
|
return tmd_chunks[index].size;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<u8, 16> TitleMetadata::GetContentCTRByIndex(u16 index) const {
|
std::array<u8, 16> TitleMetadata::GetContentCTRByIndex(std::size_t index) const {
|
||||||
std::array<u8, 16> ctr{};
|
std::array<u8, 16> ctr{};
|
||||||
std::memcpy(ctr.data(), &tmd_chunks[index].index, sizeof(u16));
|
std::memcpy(ctr.data(), &tmd_chunks[index].index, sizeof(u16));
|
||||||
return ctr;
|
return ctr;
|
||||||
|
|
|
@ -96,10 +96,10 @@ public:
|
||||||
u32 GetBootContentID() const;
|
u32 GetBootContentID() const;
|
||||||
u32 GetManualContentID() const;
|
u32 GetManualContentID() const;
|
||||||
u32 GetDLPContentID() const;
|
u32 GetDLPContentID() const;
|
||||||
u32 GetContentIDByIndex(u16 index) const;
|
u32 GetContentIDByIndex(std::size_t index) const;
|
||||||
u16 GetContentTypeByIndex(u16 index) const;
|
u16 GetContentTypeByIndex(std::size_t index) const;
|
||||||
u64 GetContentSizeByIndex(u16 index) const;
|
u64 GetContentSizeByIndex(std::size_t index) const;
|
||||||
std::array<u8, 16> GetContentCTRByIndex(u16 index) const;
|
std::array<u8, 16> GetContentCTRByIndex(std::size_t index) const;
|
||||||
|
|
||||||
void SetTitleID(u64 title_id);
|
void SetTitleID(u64 title_id);
|
||||||
void SetTitleType(u32 type);
|
void SetTitleType(u32 type);
|
||||||
|
|
|
@ -151,21 +151,22 @@ ResultVal<std::size_t> CIAFile::WriteContentData(u64 offset, std::size_t length,
|
||||||
// Data is not being buffered, so we have to keep track of how much of each <ID>.app
|
// Data is not being buffered, so we have to keep track of how much of each <ID>.app
|
||||||
// has been written since we might get a written buffer which contains multiple .app
|
// has been written since we might get a written buffer which contains multiple .app
|
||||||
// contents or only part of a larger .app's contents.
|
// contents or only part of a larger .app's contents.
|
||||||
u64 offset_max = offset + length;
|
const u64 offset_max = offset + length;
|
||||||
for (int i = 0; i < container.GetTitleMetadata().GetContentCount(); i++) {
|
for (std::size_t i = 0; i < container.GetTitleMetadata().GetContentCount(); i++) {
|
||||||
if (content_written[i] < container.GetContentSize(i)) {
|
if (content_written[i] < container.GetContentSize(i)) {
|
||||||
// The size, minimum unwritten offset, and maximum unwritten offset of this content
|
// The size, minimum unwritten offset, and maximum unwritten offset of this content
|
||||||
u64 size = container.GetContentSize(i);
|
const u64 size = container.GetContentSize(i);
|
||||||
u64 range_min = container.GetContentOffset(i) + content_written[i];
|
const u64 range_min = container.GetContentOffset(i) + content_written[i];
|
||||||
u64 range_max = container.GetContentOffset(i) + size;
|
const u64 range_max = container.GetContentOffset(i) + size;
|
||||||
|
|
||||||
// The unwritten range for this content is beyond the buffered data we have
|
// The unwritten range for this content is beyond the buffered data we have
|
||||||
// or comes before the buffered data we have, so skip this content ID.
|
// or comes before the buffered data we have, so skip this content ID.
|
||||||
if (range_min > offset_max || range_max < offset)
|
if (range_min > offset_max || range_max < offset) {
|
||||||
continue;
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Figure out how much of this content ID we have just recieved/can write out
|
// Figure out how much of this content ID we have just recieved/can write out
|
||||||
u64 available_to_write = std::min(offset_max, range_max) - range_min;
|
const u64 available_to_write = std::min(offset_max, range_max) - range_min;
|
||||||
|
|
||||||
// Since the incoming TMD has already been written, we can use GetTitleContentPath
|
// Since the incoming TMD has already been written, we can use GetTitleContentPath
|
||||||
// to get the content paths to write to.
|
// to get the content paths to write to.
|
||||||
|
@ -173,14 +174,14 @@ ResultVal<std::size_t> CIAFile::WriteContentData(u64 offset, std::size_t length,
|
||||||
FileUtil::IOFile file(GetTitleContentPath(media_type, tmd.GetTitleID(), i, is_update),
|
FileUtil::IOFile file(GetTitleContentPath(media_type, tmd.GetTitleID(), i, is_update),
|
||||||
content_written[i] ? "ab" : "wb");
|
content_written[i] ? "ab" : "wb");
|
||||||
|
|
||||||
if (!file.IsOpen())
|
if (!file.IsOpen()) {
|
||||||
return FileSys::ERROR_INSUFFICIENT_SPACE;
|
return FileSys::ERROR_INSUFFICIENT_SPACE;
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<u8> temp(buffer + (range_min - offset),
|
std::vector<u8> temp(buffer + (range_min - offset),
|
||||||
buffer + (range_min - offset) + available_to_write);
|
buffer + (range_min - offset) + available_to_write);
|
||||||
|
|
||||||
if (tmd.GetContentTypeByIndex(static_cast<u16>(i)) &
|
if ((tmd.GetContentTypeByIndex(i) & FileSys::TMDContentTypeFlag::Encrypted) != 0) {
|
||||||
FileSys::TMDContentTypeFlag::Encrypted) {
|
|
||||||
decryption_state->content[i].ProcessData(temp.data(), temp.data(), temp.size());
|
decryption_state->content[i].ProcessData(temp.data(), temp.data(), temp.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -194,7 +195,7 @@ ResultVal<std::size_t> CIAFile::WriteContentData(u64 offset, std::size_t length,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return MakeResult<std::size_t>(length);
|
return MakeResult(length);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultVal<std::size_t> CIAFile::Write(u64 offset, std::size_t length, bool flush,
|
ResultVal<std::size_t> CIAFile::Write(u64 offset, std::size_t length, bool flush,
|
||||||
|
@ -464,11 +465,10 @@ std::string GetTitleMetadataPath(Service::FS::MediaType media_type, u64 tid, boo
|
||||||
return content_path + fmt::format("{:08x}.tmd", (update ? update_id : base_id));
|
return content_path + fmt::format("{:08x}.tmd", (update ? update_id : base_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string GetTitleContentPath(Service::FS::MediaType media_type, u64 tid, u16 index,
|
std::string GetTitleContentPath(FS::MediaType media_type, u64 tid, std::size_t index, bool update) {
|
||||||
bool update) {
|
|
||||||
std::string content_path = GetTitlePath(media_type, tid) + "content/";
|
std::string content_path = GetTitlePath(media_type, tid) + "content/";
|
||||||
|
|
||||||
if (media_type == Service::FS::MediaType::GameCard) {
|
if (media_type == FS::MediaType::GameCard) {
|
||||||
// TODO(shinyquagsire23): get current app file if TID matches?
|
// TODO(shinyquagsire23): get current app file if TID matches?
|
||||||
LOG_ERROR(Service_AM, "Request for gamecard partition {} content path unimplemented!",
|
LOG_ERROR(Service_AM, "Request for gamecard partition {} content path unimplemented!",
|
||||||
static_cast<u32>(index));
|
static_cast<u32>(index));
|
||||||
|
|
|
@ -134,7 +134,7 @@ std::string GetTitleMetadataPath(Service::FS::MediaType media_type, u64 tid, boo
|
||||||
* @param update set true if the incoming TMD should be used instead of the current TMD
|
* @param update set true if the incoming TMD should be used instead of the current TMD
|
||||||
* @returns string path to the .app file
|
* @returns string path to the .app file
|
||||||
*/
|
*/
|
||||||
std::string GetTitleContentPath(Service::FS::MediaType media_type, u64 tid, u16 index = 0,
|
std::string GetTitleContentPath(FS::MediaType media_type, u64 tid, std::size_t index = 0,
|
||||||
bool update = false);
|
bool update = false);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
Reference in New Issue