mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-05-20 18:05:11 -04:00
erpt: implement forced shutdown detection
This commit is contained in:
parent
ef0c15b764
commit
355010ad84
17 changed files with 645 additions and 53 deletions
|
@ -19,7 +19,8 @@
|
|||
|
||||
namespace ams::erpt::srv {
|
||||
|
||||
bool Stream::s_can_access_fs = true;
|
||||
constinit bool Stream::s_can_access_fs = true;
|
||||
constinit os::SdkMutex Stream::s_fs_commit_mutex;
|
||||
|
||||
void Stream::EnableFsAccess(bool en) {
|
||||
s_can_access_fs = en;
|
||||
|
@ -32,6 +33,9 @@ namespace ams::erpt::srv {
|
|||
|
||||
Result Stream::CommitStream() {
|
||||
R_UNLESS(s_can_access_fs, erpt::ResultInvalidPowerState());
|
||||
|
||||
std::scoped_lock lk(s_fs_commit_mutex);
|
||||
|
||||
fs::CommitSaveData(ReportStoragePath);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
@ -52,13 +56,22 @@ namespace ams::erpt::srv {
|
|||
|
||||
Stream::~Stream() {
|
||||
this->CloseStream();
|
||||
AMS_ASSERT(!s_fs_commit_mutex.IsLockedByCurrentThread());
|
||||
}
|
||||
|
||||
Result Stream::OpenStream(const char *path, StreamMode mode, u32 buffer_size) {
|
||||
R_UNLESS(s_can_access_fs, erpt::ResultInvalidPowerState());
|
||||
R_UNLESS(!this->initialized, erpt::ResultAlreadyInitialized());
|
||||
|
||||
auto lock_guard = SCOPE_GUARD {
|
||||
if (s_fs_commit_mutex.IsLockedByCurrentThread()) {
|
||||
s_fs_commit_mutex.Unlock();
|
||||
}
|
||||
};
|
||||
|
||||
if (mode == StreamMode_Write) {
|
||||
s_fs_commit_mutex.Lock();
|
||||
|
||||
while (true) {
|
||||
R_TRY_CATCH(fs::OpenFile(std::addressof(this->file_handle), path, fs::OpenMode_Write | fs::OpenMode_AllowAppend)) {
|
||||
R_CATCH(fs::ResultPathNotFound) {
|
||||
|
@ -71,16 +84,23 @@ namespace ams::erpt::srv {
|
|||
fs::SetFileSize(this->file_handle, 0);
|
||||
} else {
|
||||
R_UNLESS(mode == StreamMode_Read, erpt::ResultInvalidArgument());
|
||||
|
||||
fs::OpenFile(std::addressof(this->file_handle), path, fs::OpenMode_Read);
|
||||
}
|
||||
auto file_guard = SCOPE_GUARD { if (mode == StreamMode_Write) { fs::CloseFile(this->file_handle); } };
|
||||
auto file_guard = SCOPE_GUARD { fs::CloseFile(this->file_handle); };
|
||||
|
||||
std::strncpy(this->file_name, path, sizeof(this->file_name));
|
||||
this->file_name[sizeof(this->file_name) - 1] = '\x00';
|
||||
|
||||
this->buffer = reinterpret_cast<u8 *>(Allocate(buffer_size));
|
||||
R_UNLESS(this->buffer != nullptr, erpt::ResultOutOfMemory());
|
||||
if (buffer_size > 0) {
|
||||
this->buffer = reinterpret_cast<u8 *>(Allocate(buffer_size));
|
||||
AMS_ASSERT(this->buffer != nullptr);
|
||||
} else {
|
||||
this->buffer = nullptr;
|
||||
}
|
||||
|
||||
this->buffer_size = buffer_size;
|
||||
|
||||
this->buffer_size = this->buffer != nullptr ? buffer_size : 0;
|
||||
this->buffer_count = 0;
|
||||
this->buffer_position = 0;
|
||||
this->file_position = 0;
|
||||
|
@ -88,6 +108,7 @@ namespace ams::erpt::srv {
|
|||
this->initialized = true;
|
||||
|
||||
file_guard.Cancel();
|
||||
lock_guard.Cancel();
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
|
@ -98,42 +119,38 @@ namespace ams::erpt::srv {
|
|||
R_UNLESS(out != nullptr, erpt::ResultInvalidArgument());
|
||||
R_UNLESS(dst != nullptr, erpt::ResultInvalidArgument());
|
||||
|
||||
fs::FileHandle tmp_file;
|
||||
size_t fs_read_size;
|
||||
u32 read_count = 0;
|
||||
bool opened = false;
|
||||
|
||||
ON_SCOPE_EXIT {
|
||||
*out = read_count;
|
||||
|
||||
if (opened) {
|
||||
fs::CloseFile(tmp_file);
|
||||
}
|
||||
};
|
||||
|
||||
while (dst_size > 0) {
|
||||
if (u32 cur = std::min<u32>(this->buffer_count - this->buffer_position, dst_size); cur > 0) {
|
||||
std::memcpy(dst, this->buffer + this->buffer_position, cur);
|
||||
this->buffer_position += cur;
|
||||
dst += cur;
|
||||
dst_size -= cur;
|
||||
read_count += cur;
|
||||
} else {
|
||||
if (!opened) {
|
||||
R_TRY(fs::OpenFile(std::addressof(tmp_file), this->file_name, fs::OpenMode_Read));
|
||||
opened = true;
|
||||
}
|
||||
if (this->buffer != nullptr) {
|
||||
while (dst_size > 0) {
|
||||
if (u32 cur = std::min<u32>(this->buffer_count - this->buffer_position, dst_size); cur > 0) {
|
||||
std::memcpy(dst, this->buffer + this->buffer_position, cur);
|
||||
this->buffer_position += cur;
|
||||
dst += cur;
|
||||
dst_size -= cur;
|
||||
read_count += cur;
|
||||
} else {
|
||||
R_TRY(fs::ReadFile(std::addressof(fs_read_size), this->file_handle, this->file_position, this->buffer, this->buffer_size));
|
||||
|
||||
R_TRY(fs::ReadFile(std::addressof(fs_read_size), tmp_file, this->file_position, this->buffer, this->buffer_size));
|
||||
this->buffer_position = 0;
|
||||
this->file_position += static_cast<u32>(fs_read_size);
|
||||
this->buffer_count = static_cast<u32>(fs_read_size);
|
||||
|
||||
this->buffer_position = 0;
|
||||
this->file_position += static_cast<u32>(fs_read_size);
|
||||
this->buffer_count = static_cast<u32>(fs_read_size);
|
||||
|
||||
if (this->buffer_count == 0) {
|
||||
break;
|
||||
if (this->buffer_count == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
R_TRY(fs::ReadFile(std::addressof(fs_read_size), this->file_handle, this->file_position, dst, dst_size));
|
||||
|
||||
this->file_position += static_cast<u32>(fs_read_size);
|
||||
read_count = static_cast<u32>(fs_read_size);
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
|
@ -145,17 +162,22 @@ namespace ams::erpt::srv {
|
|||
R_UNLESS(this->stream_mode == StreamMode_Write, erpt::ResultNotInitialized());
|
||||
R_UNLESS(src != nullptr || src_size == 0, erpt::ResultInvalidArgument());
|
||||
|
||||
while (src_size > 0) {
|
||||
if (u32 cur = std::min<u32>(this->buffer_size - this->buffer_count, src_size); cur > 0) {
|
||||
std::memcpy(this->buffer + this->buffer_count, src, cur);
|
||||
this->buffer_count += cur;
|
||||
src += cur;
|
||||
src_size -= cur;
|
||||
}
|
||||
if (this->buffer != nullptr) {
|
||||
while (src_size > 0) {
|
||||
if (u32 cur = std::min<u32>(this->buffer_size - this->buffer_count, src_size); cur > 0) {
|
||||
std::memcpy(this->buffer + this->buffer_count, src, cur);
|
||||
this->buffer_count += cur;
|
||||
src += cur;
|
||||
src_size -= cur;
|
||||
}
|
||||
|
||||
if (this->buffer_count == this->buffer_size) {
|
||||
R_TRY(this->Flush());
|
||||
if (this->buffer_count == this->buffer_size) {
|
||||
R_TRY(this->Flush());
|
||||
}
|
||||
}
|
||||
} else {
|
||||
R_TRY(fs::WriteFile(this->file_handle, this->file_position, src, src_size, fs::WriteOption::None));
|
||||
this->file_position += src_size;
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
|
@ -163,13 +185,23 @@ namespace ams::erpt::srv {
|
|||
|
||||
void Stream::CloseStream() {
|
||||
if (this->initialized) {
|
||||
if (s_can_access_fs && this->stream_mode == StreamMode_Write) {
|
||||
this->Flush();
|
||||
fs::FlushFile(this->file_handle);
|
||||
if (s_can_access_fs) {
|
||||
if (this->stream_mode == StreamMode_Write) {
|
||||
this->Flush();
|
||||
fs::FlushFile(this->file_handle);
|
||||
}
|
||||
fs::CloseFile(this->file_handle);
|
||||
}
|
||||
Deallocate(this->buffer);
|
||||
|
||||
if (this->buffer != nullptr) {
|
||||
Deallocate(this->buffer);
|
||||
}
|
||||
|
||||
this->initialized = false;
|
||||
|
||||
if (s_fs_commit_mutex.IsLockedByCurrentThread()) {
|
||||
s_fs_commit_mutex.Unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,6 +210,8 @@ namespace ams::erpt::srv {
|
|||
}
|
||||
|
||||
Result Stream::Flush() {
|
||||
AMS_ASSERT(s_fs_commit_mutex.IsLockedByCurrentThread());
|
||||
|
||||
R_SUCCEED_IF(this->buffer_count == 0);
|
||||
R_TRY(fs::WriteFile(this->file_handle, this->file_position, this->buffer, this->buffer_count, fs::WriteOption::None));
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue