From 797815b838207033f327fe3a75977d26777e8431 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Wed, 4 Mar 2020 01:46:13 -0800 Subject: [PATCH] kvdb: use fs:: --- .../stratosphere/kvdb/kvdb_bounded_string.hpp | 2 + .../kvdb/kvdb_file_key_value_cache.hpp | 68 ++++++++--------- .../kvdb/kvdb_memory_key_value_store.hpp | 70 ++++++++++-------- .../source/kvdb/kvdb_file_key_value_store.cpp | 74 +++++++++---------- 4 files changed, 104 insertions(+), 110 deletions(-) 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(); }