Files
Xenia-Canary/src/xenia/vfs/devices/stfs_container_file.cc
emoose 422fc4f24e [VFS/STFS] Check fread return values, add SVOD local structs
A few minor improvements to StfsContainerDevice too, and now StfsContainerFile::ReadSync will set out_bytes_read to the actual
number of bytes read
2021-05-18 09:04:45 -05:00

72 lines
2.2 KiB
C++

/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2014 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#include "xenia/vfs/devices/stfs_container_file.h"
#include <algorithm>
#include <cmath>
#include "xenia/base/math.h"
#include "xenia/vfs/devices/stfs_container_entry.h"
namespace xe {
namespace vfs {
StfsContainerFile::StfsContainerFile(uint32_t file_access,
StfsContainerEntry* entry)
: File(file_access, entry), entry_(entry) {}
StfsContainerFile::~StfsContainerFile() = default;
void StfsContainerFile::Destroy() { delete this; }
X_STATUS StfsContainerFile::ReadSync(void* buffer, size_t buffer_length,
size_t byte_offset,
size_t* out_bytes_read) {
if (byte_offset >= entry_->size()) {
return X_STATUS_END_OF_FILE;
}
size_t src_offset = 0;
uint8_t* p = reinterpret_cast<uint8_t*>(buffer);
size_t remaining_length =
std::min(buffer_length, entry_->size() - byte_offset);
*out_bytes_read = 0;
for (size_t i = 0; i < entry_->block_list().size(); i++) {
auto& record = entry_->block_list()[i];
if (src_offset + record.length <= byte_offset) {
// Doesn't begin in this region. Skip it.
src_offset += record.length;
continue;
}
size_t read_offset =
(byte_offset > src_offset) ? byte_offset - src_offset : 0;
size_t read_length =
std::min(record.length - read_offset, remaining_length);
auto& file = entry_->files()->at(record.file);
xe::filesystem::Seek(file, record.offset + read_offset, SEEK_SET);
auto num_read = fread(p, 1, read_length, file);
*out_bytes_read += num_read;
p += num_read;
src_offset += record.length;
remaining_length -= read_length;
if (remaining_length == 0) {
break;
}
}
return X_STATUS_SUCCESS;
}
} // namespace vfs
} // namespace xe