mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-11-22 02:32:36 +01:00
fs: implement file::read_at
Reads from the given offset; does not seek; thread-safe.
This commit is contained in:
parent
9d432187aa
commit
2f9cac8d18
@ -1106,10 +1106,12 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
|||||||
class windows_file final : public file_base
|
class windows_file final : public file_base
|
||||||
{
|
{
|
||||||
const HANDLE m_handle;
|
const HANDLE m_handle;
|
||||||
|
atomic_t<u64> m_pos;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
windows_file(HANDLE handle)
|
windows_file(HANDLE handle)
|
||||||
: m_handle(handle)
|
: m_handle(handle)
|
||||||
|
, m_pos(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1165,7 +1167,39 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
|||||||
const DWORD size = static_cast<DWORD>(std::min<u64>(count, DWORD{umax} & -4096));
|
const DWORD size = static_cast<DWORD>(std::min<u64>(count, DWORD{umax} & -4096));
|
||||||
|
|
||||||
DWORD nread = 0;
|
DWORD nread = 0;
|
||||||
ensure(ReadFile(m_handle, data, size, &nread, nullptr)); // "file::read"
|
OVERLAPPED ovl{};
|
||||||
|
const u64 pos = m_pos;
|
||||||
|
ovl.Offset = DWORD(pos);
|
||||||
|
ovl.OffsetHigh = DWORD(pos >> 32);
|
||||||
|
ensure(ReadFile(m_handle, data, size, &nread, &ovl) || GetLastError() == ERROR_HANDLE_EOF); // "file::read"
|
||||||
|
nread_sum += nread;
|
||||||
|
m_pos += nread;
|
||||||
|
|
||||||
|
if (nread < size)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
count -= size;
|
||||||
|
data += size;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nread_sum;
|
||||||
|
}
|
||||||
|
|
||||||
|
u64 read_at(u64 offset, void* buffer, u64 count) override
|
||||||
|
{
|
||||||
|
u64 nread_sum = 0;
|
||||||
|
|
||||||
|
for (char* data = static_cast<char*>(buffer); count;)
|
||||||
|
{
|
||||||
|
const DWORD size = static_cast<DWORD>(std::min<u64>(count, DWORD{umax} & -4096));
|
||||||
|
|
||||||
|
DWORD nread = 0;
|
||||||
|
OVERLAPPED ovl{};
|
||||||
|
ovl.Offset = DWORD(offset);
|
||||||
|
ovl.OffsetHigh = DWORD(offset >> 32);
|
||||||
|
ensure(ReadFile(m_handle, data, size, &nread, &ovl) || GetLastError() == ERROR_HANDLE_EOF); // "file::read"
|
||||||
nread_sum += nread;
|
nread_sum += nread;
|
||||||
|
|
||||||
if (nread < size)
|
if (nread < size)
|
||||||
@ -1175,6 +1209,7 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
|||||||
|
|
||||||
count -= size;
|
count -= size;
|
||||||
data += size;
|
data += size;
|
||||||
|
offset += size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return nread_sum;
|
return nread_sum;
|
||||||
@ -1189,8 +1224,13 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
|||||||
const DWORD size = static_cast<DWORD>(std::min<u64>(count, DWORD{umax} & -4096));
|
const DWORD size = static_cast<DWORD>(std::min<u64>(count, DWORD{umax} & -4096));
|
||||||
|
|
||||||
DWORD nwritten = 0;
|
DWORD nwritten = 0;
|
||||||
ensure(WriteFile(m_handle, data, size, &nwritten, nullptr)); // "file::write"
|
OVERLAPPED ovl{};
|
||||||
|
const u64 pos = m_pos;
|
||||||
|
ovl.Offset = DWORD(pos);
|
||||||
|
ovl.OffsetHigh = DWORD(pos >> 32);
|
||||||
|
ensure(WriteFile(m_handle, data, size, &nwritten, &ovl)); // "file::write"
|
||||||
nwritten_sum += nwritten;
|
nwritten_sum += nwritten;
|
||||||
|
m_pos += nwritten;
|
||||||
|
|
||||||
if (nwritten < size)
|
if (nwritten < size)
|
||||||
{
|
{
|
||||||
@ -1211,20 +1251,19 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
|||||||
fmt::throw_exception("Invalid whence (0x%x)", whence);
|
fmt::throw_exception("Invalid whence (0x%x)", whence);
|
||||||
}
|
}
|
||||||
|
|
||||||
LARGE_INTEGER pos;
|
const s64 new_pos =
|
||||||
pos.QuadPart = offset;
|
whence == fs::seek_set ? offset :
|
||||||
|
whence == fs::seek_cur ? offset + m_pos :
|
||||||
|
whence == fs::seek_end ? offset + size() : -1;
|
||||||
|
|
||||||
const DWORD mode =
|
if (new_pos < 0)
|
||||||
whence == seek_set ? FILE_BEGIN :
|
|
||||||
whence == seek_cur ? FILE_CURRENT : FILE_END;
|
|
||||||
|
|
||||||
if (!SetFilePointerEx(m_handle, pos, &pos, mode))
|
|
||||||
{
|
{
|
||||||
g_tls_error = to_error(GetLastError());
|
fs::g_tls_error = fs::error::inval;
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pos.QuadPart;
|
m_pos = new_pos;
|
||||||
|
return m_pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 size() override
|
u64 size() override
|
||||||
@ -1349,6 +1388,14 @@ fs::file::file(const std::string& path, bs_t<open_mode> mode)
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 read_at(u64 offset, void* buffer, u64 count) override
|
||||||
|
{
|
||||||
|
const auto result = ::pread(m_fd, buffer, count, offset);
|
||||||
|
ensure(result != -1);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
u64 write(const void* buffer, u64 count) override
|
u64 write(const void* buffer, u64 count) override
|
||||||
{
|
{
|
||||||
const auto result = ::write(m_fd, buffer, count);
|
const auto result = ::write(m_fd, buffer, count);
|
||||||
@ -1466,6 +1513,21 @@ fs::file::file(const void* ptr, usz size)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 read_at(u64 offset, void* buffer, u64 count) override
|
||||||
|
{
|
||||||
|
if (offset < m_size)
|
||||||
|
{
|
||||||
|
// Get readable size
|
||||||
|
if (const u64 result = std::min<u64>(count, m_size - offset))
|
||||||
|
{
|
||||||
|
std::memcpy(buffer, m_ptr + offset, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
u64 write(const void*, u64) override
|
u64 write(const void*, u64) override
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -1951,6 +2013,40 @@ fs::file fs::make_gather(std::vector<fs::file> files)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 read_at(u64 start, void* buffer, u64 size) override
|
||||||
|
{
|
||||||
|
if (start < end)
|
||||||
|
{
|
||||||
|
u64 pos = start;
|
||||||
|
|
||||||
|
// Get readable size
|
||||||
|
if (const u64 max = std::min<u64>(size, end - pos))
|
||||||
|
{
|
||||||
|
u8* buf_out = static_cast<u8*>(buffer);
|
||||||
|
u64 buf_max = max;
|
||||||
|
|
||||||
|
for (auto it = ends.upper_bound(pos); it != ends.end(); ++it)
|
||||||
|
{
|
||||||
|
const u64 count = std::min<u64>(it->first - pos, buf_max);
|
||||||
|
const u64 read = files[it->second].read_at(files[it->second].size() + pos - it->first, buf_out, count);
|
||||||
|
|
||||||
|
buf_out += count;
|
||||||
|
buf_max -= count;
|
||||||
|
pos += read;
|
||||||
|
|
||||||
|
if (read < count || buf_max == 0)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return pos - start;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
u64 write(const void*, u64) override
|
u64 write(const void*, u64) override
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -93,6 +93,7 @@ namespace fs
|
|||||||
virtual void sync();
|
virtual void sync();
|
||||||
virtual bool trunc(u64 length) = 0;
|
virtual bool trunc(u64 length) = 0;
|
||||||
virtual u64 read(void* buffer, u64 size) = 0;
|
virtual u64 read(void* buffer, u64 size) = 0;
|
||||||
|
virtual u64 read_at(u64 offset, void* buffer, u64 size) = 0;
|
||||||
virtual u64 write(const void* buffer, u64 size) = 0;
|
virtual u64 write(const void* buffer, u64 size) = 0;
|
||||||
virtual u64 seek(s64 offset, seek_mode whence) = 0;
|
virtual u64 seek(s64 offset, seek_mode whence) = 0;
|
||||||
virtual u64 size() = 0;
|
virtual u64 size() = 0;
|
||||||
@ -301,6 +302,17 @@ namespace fs
|
|||||||
return m_file->read(buffer, count);
|
return m_file->read(buffer, count);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Read the data from the file at specified offset in thread-safe manner
|
||||||
|
u64 read_at(u64 offset, void* buffer, u64 count,
|
||||||
|
u32 line = __builtin_LINE(),
|
||||||
|
u32 col = __builtin_COLUMN(),
|
||||||
|
const char* file = __builtin_FILE(),
|
||||||
|
const char* func = __builtin_FUNCTION()) const
|
||||||
|
{
|
||||||
|
if (!m_file) xnull({line, col, file, func});
|
||||||
|
return m_file->read_at(offset, buffer, count);
|
||||||
|
}
|
||||||
|
|
||||||
// Write the data to the file and return the amount of data actually written
|
// Write the data to the file and return the amount of data actually written
|
||||||
u64 write(const void* buffer, u64 count,
|
u64 write(const void* buffer, u64 count,
|
||||||
u32 line = __builtin_LINE(),
|
u32 line = __builtin_LINE(),
|
||||||
@ -724,6 +736,24 @@ namespace fs
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 read_at(u64 offset, void* buffer, u64 size) override
|
||||||
|
{
|
||||||
|
const u64 end = obj.size();
|
||||||
|
|
||||||
|
if (offset < end)
|
||||||
|
{
|
||||||
|
// Get readable size
|
||||||
|
if (const u64 max = std::min<u64>(size, end - offset))
|
||||||
|
{
|
||||||
|
std::copy(obj.cbegin() + offset, obj.cbegin() + offset + max, static_cast<value_type*>(buffer));
|
||||||
|
update_time();
|
||||||
|
return max;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
u64 write(const void* buffer, u64 size) override
|
u64 write(const void* buffer, u64 size) override
|
||||||
{
|
{
|
||||||
const u64 old_size = obj.size();
|
const u64 old_size = obj.size();
|
||||||
|
@ -115,6 +115,11 @@ public:
|
|||||||
return bytesRead;
|
return bytesRead;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 read_at(u64 offset, void* buffer, u64 size) override
|
||||||
|
{
|
||||||
|
return ReadData(offset, static_cast<u8*>(buffer), size);
|
||||||
|
}
|
||||||
|
|
||||||
u64 write(const void*, u64) override
|
u64 write(const void*, u64) override
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -617,7 +617,7 @@ struct ppu_far_jumps_t
|
|||||||
bool with_toc;
|
bool with_toc;
|
||||||
std::string module_name;
|
std::string module_name;
|
||||||
ppu_intrp_func_t func;
|
ppu_intrp_func_t func;
|
||||||
|
|
||||||
u32 get_target(u32 pc, ppu_thread* ppu = nullptr) const
|
u32 get_target(u32 pc, ppu_thread* ppu = nullptr) const
|
||||||
{
|
{
|
||||||
u32 direct_target = this->target;
|
u32 direct_target = this->target;
|
||||||
@ -706,7 +706,7 @@ struct ppu_far_jumps_t
|
|||||||
{
|
{
|
||||||
return targets;
|
return targets;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto end = vals.lower_bound(pc + size); it != end; it++)
|
for (auto end = vals.lower_bound(pc + size); it != end; it++)
|
||||||
{
|
{
|
||||||
all_info_t& all_info = it->second;
|
all_info_t& all_info = it->second;
|
||||||
@ -1994,7 +1994,7 @@ void ppu_thread::fast_call(u32 addr, u64 rtoc)
|
|||||||
|
|
||||||
if (auto name = get_prx_name_by_cia(cia))
|
if (auto name = get_prx_name_by_cia(cia))
|
||||||
{
|
{
|
||||||
return fmt::format("PPU[0x%x] Thread (%s) [%s: 0x%08x]", _this->id, *name_cache.get(), name, cia);
|
return fmt::format("PPU[0x%x] Thread (%s) [%s: 0x%08x]", _this->id, *name_cache.get(), name, cia);
|
||||||
}
|
}
|
||||||
|
|
||||||
return fmt::format("PPU[0x%x] Thread (%s) [0x%08x]", _this->id, *name_cache.get(), cia);
|
return fmt::format("PPU[0x%x] Thread (%s) [0x%08x]", _this->id, *name_cache.get(), cia);
|
||||||
@ -2806,6 +2806,11 @@ namespace
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 read_at(u64 offset, void* buffer, u64 size) override
|
||||||
|
{
|
||||||
|
return m_file.read_at(offset + m_off, buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
u64 write(const void*, u64) override
|
u64 write(const void*, u64) override
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -579,6 +579,11 @@ struct lv2_file::file_view : fs::file_base
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u64 read_at(u64 offset, void* buffer, u64 size) override
|
||||||
|
{
|
||||||
|
return m_file->file.read_at(offset, buffer, size);
|
||||||
|
}
|
||||||
|
|
||||||
u64 write(const void*, u64) override
|
u64 write(const void*, u64) override
|
||||||
{
|
{
|
||||||
return 0;
|
return 0;
|
||||||
@ -2380,7 +2385,7 @@ error_code sys_fs_fcntl(ppu_thread& ppu, u32 fd, u32 op, vm::ptr<void> _arg, u32
|
|||||||
strcpy_trunc(entry.entry_name.d_name, info->name);
|
strcpy_trunc(entry.entry_name.d_name, info->name);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Apparently all this function does to additional buffer elements is to zeroize them
|
// Apparently all this function does to additional buffer elements is to zeroize them
|
||||||
std::memset(arg_ptr.get_ptr() + read_count, 0, (max - read_count) * arg->ptr.size());
|
std::memset(arg_ptr.get_ptr() + read_count, 0, (max - read_count) * arg->ptr.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user