diff --git a/libraries/libstratosphere/include/stratosphere/kvdb/kvdb_bounded_string.hpp b/libraries/libstratosphere/include/stratosphere/kvdb/kvdb_bounded_string.hpp
index 7d0aec0b0..dcef1765c 100644
--- a/libraries/libstratosphere/include/stratosphere/kvdb/kvdb_bounded_string.hpp
+++ b/libraries/libstratosphere/include/stratosphere/kvdb/kvdb_bounded_string.hpp
@@ -51,6 +51,7 @@ namespace ams::kvdb {
std::va_list args;
va_start(args, format);
CheckLength(std::vsnprintf(string.buffer, N, format, args));
+ string.buffer[N - 1] = 0;
va_end(args);
return string;
@@ -74,6 +75,7 @@ namespace ams::kvdb {
/* Ensure string can fit in our buffer. */
CheckLength(strnlen(s, N));
std::strncpy(this->buffer, s, N);
+ this->buffer[N - 1] = 0;
}
void SetFormat(const char *format, ...) __attribute__((format (printf, 2, 3))) {
diff --git a/libraries/libstratosphere/include/stratosphere/kvdb/kvdb_file_key_value_cache.hpp b/libraries/libstratosphere/include/stratosphere/kvdb/kvdb_file_key_value_cache.hpp
index c98c25188..f3e969440 100644
--- a/libraries/libstratosphere/include/stratosphere/kvdb/kvdb_file_key_value_cache.hpp
+++ b/libraries/libstratosphere/include/stratosphere/kvdb/kvdb_file_key_value_cache.hpp
@@ -13,7 +13,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
-#include
+#include
#include "kvdb_bounded_string.hpp"
#include "kvdb_file_key_value_store.hpp"
@@ -39,16 +39,16 @@ namespace ams::kvdb {
public:
static Result CreateNewList(const char *path) {
/* Create new lru_list.dat. */
- R_TRY(fsdevCreateFile(path, FileSize, 0));
+ R_TRY(fs::CreateFile(path, FileSize));
/* Open the file. */
- FILE *fp = fopen(path, "r+b");
- R_UNLESS(fp != nullptr, fsdevGetLastResult());
- ON_SCOPE_EXIT { fclose(fp); };
+ fs::FileHandle file;
+ R_TRY(fs::OpenFile(std::addressof(file), path, fs::OpenMode_Write));
+ ON_SCOPE_EXIT { fs::CloseFile(file); };
/* Write new header with zero entries to the file. */
LruHeader new_header = { .entry_count = 0, };
- R_UNLESS(fwrite(&new_header, sizeof(new_header), 1, fp) == 1, fsdevGetLastResult());
+ R_TRY(fs::WriteFile(file, 0, std::addressof(new_header), sizeof(new_header), fs::WriteOption::Flush));
return ResultSuccess();
}
@@ -80,36 +80,33 @@ namespace ams::kvdb {
std::memset(this->keys, 0, BufferSize);
/* Open file. */
- FILE *fp = fopen(this->file_path, "rb");
- R_UNLESS(fp != nullptr, fsdevGetLastResult());
- ON_SCOPE_EXIT { fclose(fp); };
+ fs::FileHandle file;
+ R_TRY(fs::OpenFile(std::addressof(file), this->file_path, fs::OpenMode_Read));
+ ON_SCOPE_EXIT { fs::CloseFile(file); };
/* Read header. */
- R_UNLESS(fread(&this->header, sizeof(this->header), 1, fp) == 1, fsdevGetLastResult());
+ R_TRY(fs::ReadFile(file, 0, std::addressof(this->header), sizeof(this->header)));
/* Read entries. */
- const size_t count = this->GetCount();
- if (count > 0) {
- R_UNLESS(fread(this->keys, std::min(BufferSize, sizeof(Key) * count), 1, fp) == 1, fsdevGetLastResult());
- }
+ R_TRY(fs::ReadFile(file, sizeof(this->header), this->keys, BufferSize));
return ResultSuccess();
}
Result Save() {
/* Open file. */
- FILE *fp = fopen(this->file_path, "r+b");
- R_UNLESS(fp != nullptr, fsdevGetLastResult());
- ON_SCOPE_EXIT { fclose(fp); };
+ fs::FileHandle file;
+ R_TRY(fs::OpenFile(std::addressof(file), this->file_path, fs::OpenMode_Read));
+ ON_SCOPE_EXIT { fs::CloseFile(file); };
/* Write header. */
- R_UNLESS(fwrite(&this->header, sizeof(this->header), 1, fp) == 1, fsdevGetLastResult());
+ R_TRY(fs::WriteFile(file, 0, std::addressof(this->header), sizeof(this->header), fs::WriteOption::None));
/* Write entries. */
- R_UNLESS(fwrite(this->keys, BufferSize, 1, fp) == 1, fsdevGetLastResult());
+ R_TRY(fs::WriteFile(file, sizeof(this->header), this->keys, BufferSize, fs::WriteOption::None));
/* Flush. */
- fflush(fp);
+ R_TRY(fs::FlushFile(file));
return ResultSuccess();
}
@@ -209,38 +206,31 @@ namespace ams::kvdb {
return Path::MakeFormat("%s/%s", dir, "kvs");
}
- static Result Exists(bool *out, const char *path, bool is_dir) {
+ static Result Exists(bool *out, const char *path, fs::DirectoryEntryType type) {
/* Set out to false initially. */
*out = false;
- /* Check that the path exists, and that our entry type is correct. */
- {
- struct stat st;
+ /* Try to get the entry type. */
+ fs::DirectoryEntryType entry_type;
+ R_TRY_CATCH(fs::GetEntryType(std::addressof(entry_type), path)) {
+ /* If the path doesn't exist, nothing has gone wrong. */
+ R_CONVERT(fs::ResultPathNotFound, ResultSuccess());
+ } R_END_TRY_CATCH;
- if (stat(path, &st) != 0) {
- R_TRY_CATCH(fsdevGetLastResult()) {
- /* If the path doesn't exist, nothing has gone wrong. */
- R_CONVERT(fs::ResultPathNotFound, ResultSuccess());
- } R_END_TRY_CATCH;
- }
-
- if (is_dir) {
- R_UNLESS((S_ISDIR(st.st_mode)), ResultInvalidFilesystemState());
- } else {
- R_UNLESS((S_ISREG(st.st_mode)), ResultInvalidFilesystemState());
- }
- }
+ /* Check that the entry type is correct. */
+ R_UNLESS(entry_type == type, ResultInvalidFilesystemState());
+ /* The entry exists and is the correct type. */
*out = true;
return ResultSuccess();
}
static Result DirectoryExists(bool *out, const char *path) {
- return Exists(out, path, true);
+ return Exists(out, path, fs::DirectoryEntryType_Directory);
}
static Result FileExists(bool *out, const char *path) {
- return Exists(out, path, false);
+ return Exists(out, path, fs::DirectoryEntryType_File);
}
public:
static Result CreateNewCache(const char *dir) {
diff --git a/libraries/libstratosphere/include/stratosphere/kvdb/kvdb_memory_key_value_store.hpp b/libraries/libstratosphere/include/stratosphere/kvdb/kvdb_memory_key_value_store.hpp
index 00a10dfe0..fb6caa277 100644
--- a/libraries/libstratosphere/include/stratosphere/kvdb/kvdb_memory_key_value_store.hpp
+++ b/libraries/libstratosphere/include/stratosphere/kvdb/kvdb_memory_key_value_store.hpp
@@ -15,7 +15,7 @@
*/
#pragma once
-#include
+#include
#include "kvdb_auto_buffer.hpp"
#include "kvdb_archive.hpp"
#include "kvdb_bounded_string.hpp"
@@ -262,11 +262,9 @@ namespace ams::kvdb {
Result Initialize(const char *dir, size_t capacity) {
/* Ensure that the passed path is a directory. */
- {
- struct stat st;
- R_UNLESS(stat(dir, &st) == 0, fs::ResultPathNotFound());
- R_UNLESS((S_ISDIR(st.st_mode)), fs::ResultPathNotFound());
- }
+ fs::DirectoryEntryType entry_type;
+ R_TRY(fs::GetEntryType(std::addressof(entry_type), dir));
+ R_UNLESS(entry_type == fs::DirectoryEntryType_Directory, fs::ResultPathNotFound());
/* Set paths. */
this->path.SetFormat("%s%s", dir, "/imkvdb.arc");
@@ -337,7 +335,7 @@ namespace ams::kvdb {
return ResultSuccess();
}
- Result Save() {
+ Result Save(bool destructive = false) {
/* Create a buffer to hold the archive. */
AutoBuffer buffer;
R_TRY(buffer.Initialize(this->GetArchiveSize()));
@@ -353,7 +351,7 @@ namespace ams::kvdb {
}
/* Save the buffer to disk. */
- return this->Commit(buffer);
+ return this->Commit(buffer, destructive);
}
Result Set(const Key &key, const void *value, size_t value_size) {
@@ -468,27 +466,38 @@ namespace ams::kvdb {
return this->index.find(key);
}
private:
- Result Commit(const AutoBuffer &buffer) {
- /* Try to delete temporary archive, but allow deletion failure (it may not exist). */
- std::remove(this->temp_path.Get());
+ Result SaveArchiveToFile(const char *path, const void *buf, size_t size) {
+ /* Try to delete the archive, but allow deletion failure. */
+ fs::DeleteFile(path);
- /* Create new temporary archive. */
- R_TRY(fsdevCreateFile(this->temp_path.Get(), buffer.GetSize(), 0));
+ /* Create new archive. */
+ R_TRY(fs::CreateFile(path, size));
- /* Write data to the temporary archive. */
+ /* Write data to the archive. */
{
- FILE *f = fopen(this->temp_path, "r+b");
- R_UNLESS(f != nullptr, fsdevGetLastResult());
- ON_SCOPE_EXIT { fclose(f); };
-
- R_UNLESS(fwrite(buffer.Get(), buffer.GetSize(), 1, f) == 1, fsdevGetLastResult());
+ fs::FileHandle file;
+ R_TRY(fs::OpenFile(std::addressof(file), path, fs::OpenMode_Write));
+ ON_SCOPE_EXIT { fs::CloseFile(file); };
+ R_TRY(fs::WriteFile(file, 0, buf, size, fs::WriteOption::Flush));
}
- /* Try to delete the saved archive, but allow deletion failure. */
- std::remove(this->path.Get());
+ return ResultSuccess();
+ }
- /* Rename the path. */
- R_UNLESS(std::rename(this->temp_path.Get(), this->path.Get()) == 0, fsdevGetLastResult());
+ Result Commit(const AutoBuffer &buffer, bool destructive) {
+ if (destructive) {
+ /* Delete and save to the real archive. */
+ R_TRY(SaveArchiveToFile(this->path.Get(), buffer.Get(), buffer.GetSize()));
+ } else {
+ /* Delete and save to a temporary archive. */
+ R_TRY(SaveArchiveToFile(this->temp_path.Get(), buffer.Get(), buffer.GetSize()));
+
+ /* Try to delete the saved archive, but allow deletion failure. */
+ fs::DeleteFile(this->path.Get());
+
+ /* Rename the path. */
+ R_TRY(fs::RenameFile(this->temp_path.Get(), this->path.Get()));
+ }
return ResultSuccess();
}
@@ -505,18 +514,17 @@ namespace ams::kvdb {
Result ReadArchiveFile(AutoBuffer *dst) const {
/* Open the file. */
- FILE *f = fopen(this->path, "rb");
- R_UNLESS(f != nullptr, fsdevGetLastResult());
- ON_SCOPE_EXIT { fclose(f); };
+ fs::FileHandle file;
+ R_TRY(fs::OpenFile(std::addressof(file), path, fs::OpenMode_Read));
+ ON_SCOPE_EXIT { fs::CloseFile(file); };
/* Get the archive file size. */
- fseek(f, 0, SEEK_END);
- const size_t archive_size = ftell(f);
- fseek(f, 0, SEEK_SET);
+ s64 archive_size;
+ R_TRY(fs::GetFileSize(std::addressof(archive_size), file));
/* Make a new buffer, read the file. */
- R_TRY(dst->Initialize(archive_size));
- R_UNLESS(fread(dst->Get(), archive_size, 1, f) == 1, fsdevGetLastResult());
+ R_TRY(dst->Initialize(static_cast(archive_size)));
+ R_TRY(fs::ReadFile(file, 0, dst->Get(), dst->GetSize()));
return ResultSuccess();
}
diff --git a/libraries/libstratosphere/source/kvdb/kvdb_file_key_value_store.cpp b/libraries/libstratosphere/source/kvdb/kvdb_file_key_value_store.cpp
index 6a980f3ad..540ef3608 100644
--- a/libraries/libstratosphere/source/kvdb/kvdb_file_key_value_store.cpp
+++ b/libraries/libstratosphere/source/kvdb/kvdb_file_key_value_store.cpp
@@ -180,11 +180,9 @@ namespace ams::kvdb {
Result FileKeyValueStore::InitializeWithCache(const char *dir, void *cache_buffer, size_t cache_buffer_size, size_t cache_capacity) {
/* Ensure that the passed path is a directory. */
- {
- struct stat st;
- R_UNLESS(stat(dir, &st) == 0, fs::ResultPathNotFound());
- R_UNLESS((S_ISDIR(st.st_mode)), fs::ResultPathNotFound());
- }
+ fs::DirectoryEntryType entry_type;
+ R_TRY(fs::GetEntryType(std::addressof(entry_type), dir));
+ R_UNLESS(entry_type == fs::DirectoryEntryType_Directory, fs::ResultPathNotFound());
/* Set path. */
this->dir_path.Set(dir);
@@ -210,24 +208,22 @@ namespace ams::kvdb {
}
/* Open the value file. */
- FILE *fp = fopen(this->GetPath(key, key_size), "rb");
- if (fp == nullptr) {
- R_TRY_CATCH(fsdevGetLastResult()) {
- R_CONVERT(fs::ResultPathNotFound, ResultKeyNotFound())
- } R_END_TRY_CATCH;
- }
- ON_SCOPE_EXIT { fclose(fp); };
+ fs::FileHandle file;
+ R_TRY_CATCH(fs::OpenFile(std::addressof(file), this->GetPath(key, key_size), fs::OpenMode_Read)) {
+ R_CONVERT(fs::ResultPathNotFound, ResultKeyNotFound());
+ } R_END_TRY_CATCH;
+ ON_SCOPE_EXIT { fs::CloseFile(file); };
/* Get the value size. */
- fseek(fp, 0, SEEK_END);
- const size_t value_size = ftell(fp);
- fseek(fp, 0, SEEK_SET);
+ s64 file_size;
+ R_TRY(fs::GetFileSize(std::addressof(file_size), file));
/* Ensure there's enough space for the value. */
- R_UNLESS(value_size <= max_out_size, ResultBufferInsufficient());
+ R_UNLESS(file_size <= static_cast(max_out_size), ResultBufferInsufficient());
/* Read the value. */
- R_UNLESS(fread(out_value, value_size, 1, fp) == 1, fsdevGetLastResult());
+ const size_t value_size = static_cast(value_size);
+ R_TRY(fs::ReadFile(file, 0, out_value, value_size));
*out_size = value_size;
/* Cache the newly read value. */
@@ -251,17 +247,17 @@ namespace ams::kvdb {
}
/* Open the value file. */
- FILE *fp = fopen(this->GetPath(key, key_size), "rb");
- if (fp == nullptr) {
- R_TRY_CATCH(fsdevGetLastResult()) {
- R_CONVERT(fs::ResultPathNotFound, ResultKeyNotFound())
- } R_END_TRY_CATCH;
- }
- ON_SCOPE_EXIT { fclose(fp); };
+ fs::FileHandle file;
+ R_TRY_CATCH(fs::OpenFile(std::addressof(file), this->GetPath(key, key_size), fs::OpenMode_Read)) {
+ R_CONVERT(fs::ResultPathNotFound, ResultKeyNotFound());
+ } R_END_TRY_CATCH;
+ ON_SCOPE_EXIT { fs::CloseFile(file); };
/* Get the value size. */
- fseek(fp, 0, SEEK_END);
- *out_size = ftell(fp);
+ s64 file_size;
+ R_TRY(fs::GetFileSize(std::addressof(file_size), file));
+
+ *out_size = static_cast(file_size);
return ResultSuccess();
}
@@ -278,18 +274,18 @@ namespace ams::kvdb {
/* Delete the file, if it exists. Don't check result, since it's okay if it's already deleted. */
auto key_path = this->GetPath(key, key_size);
- std::remove(key_path);
+ fs::DeleteFile(key_path);
+
+ /* Create the new value file. */
+ R_TRY(fs::CreateFile(key_path, value_size));
/* Open the value file. */
- FILE *fp = fopen(key_path, "wb");
- R_UNLESS(fp != nullptr, fsdevGetLastResult());
- ON_SCOPE_EXIT { fclose(fp); };
+ fs::FileHandle file;
+ R_TRY(fs::OpenFile(std::addressof(file), key_path, fs::OpenMode_Write));
+ ON_SCOPE_EXIT { fs::CloseFile(file); };
- /* Write the value file. */
- R_UNLESS(fwrite(value, value_size, 1, fp) == 1, fsdevGetLastResult());
-
- /* Flush the value file. */
- fflush(fp);
+ /* Write the value file and flush. */
+ R_TRY(fs::WriteFile(file, 0, value, value_size, fs::WriteOption::Flush));
return ResultSuccess();
}
@@ -306,11 +302,9 @@ namespace ams::kvdb {
}
/* Remove the file. */
- if (std::remove(this->GetPath(key, key_size)) != 0) {
- R_TRY_CATCH(fsdevGetLastResult()) {
- R_CONVERT(fs::ResultPathNotFound, ResultKeyNotFound())
- } R_END_TRY_CATCH;
- }
+ R_TRY_CATCH(fs::DeleteFile(this->GetPath(key, key_size))) {
+ R_CONVERT(fs::ResultPathNotFound, ResultKeyNotFound())
+ } R_END_TRY_CATCH;
return ResultSuccess();
}