mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2025-04-22 12:34:47 +00:00
kvdb: use fs::
This commit is contained in:
parent
674fd8f1e2
commit
797815b838
4 changed files with 104 additions and 110 deletions
|
@ -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))) {
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include <sys/stat.h>
|
||||
#include <stratosphere/fs.hpp>
|
||||
#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) {
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
*/
|
||||
|
||||
#pragma once
|
||||
#include <sys/stat.h>
|
||||
#include <stratosphere/fs.hpp>
|
||||
#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<size_t>(archive_size)));
|
||||
R_TRY(fs::ReadFile(file, 0, dst->Get(), dst->GetSize()));
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
|
|
@ -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<s64>(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<size_t>(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<size_t>(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();
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue