commit 1426e3f: [Minor] More tests and fixes to raii file
Vsevolod Stakhov
vsevolod at rspamd.com
Sun Oct 16 14:28:04 UTC 2022
Author: Vsevolod Stakhov
Date: 2022-10-16 15:22:10 +0100
URL: https://github.com/rspamd/rspamd/commit/1426e3fe4ca1cd248e1cf2e35a3f946000b031e2
[Minor] More tests and fixes to raii file
---
src/libutil/cxx/locked_file.cxx | 60 +++++++++++++++++++++++++----------------
src/libutil/cxx/locked_file.hxx | 19 +++++++++++++
2 files changed, 56 insertions(+), 23 deletions(-)
diff --git a/src/libutil/cxx/locked_file.cxx b/src/libutil/cxx/locked_file.cxx
index 4c91f44ed..c972e1de3 100644
--- a/src/libutil/cxx/locked_file.cxx
+++ b/src/libutil/cxx/locked_file.cxx
@@ -41,11 +41,6 @@ auto raii_file::open(const char *fname, int flags) -> tl::expected<raii_file, st
return tl::make_unexpected(fmt::format("cannot open file {}: {}", fname, ::strerror(errno)));
}
- if (!rspamd_file_lock(fd, TRUE)) {
- close(fd);
- return tl::make_unexpected(fmt::format("cannot lock file {}: {}", fname, ::strerror(errno)));
- }
-
auto ret = raii_file{fname, fd, false};
if (fstat(ret.fd, &ret.st) == -1) {
@@ -72,11 +67,6 @@ auto raii_file::create(const char *fname, int flags, int perms) -> tl::expected<
return tl::make_unexpected(fmt::format("cannot create file {}: {}", fname, ::strerror(errno)));
}
- if (!rspamd_file_lock(fd, TRUE)) {
- close(fd);
- return tl::make_unexpected(fmt::format("cannot lock file {}: {}", fname, ::strerror(errno)));
- }
-
auto ret = raii_file{fname, fd, false};
if (fstat(ret.fd, &ret.st) == -1) {
@@ -102,12 +92,6 @@ auto raii_file::create_temp(const char *fname, int flags, int perms) -> tl::expe
return tl::make_unexpected(fmt::format("cannot create file {}: {}", fname, ::strerror(errno)));
}
- if (!rspamd_file_lock(fd, TRUE)) {
- unlink(fname);
- close(fd);
- return tl::make_unexpected(fmt::format("cannot lock file {}: {}", fname, ::strerror(errno)));
- }
-
auto ret = raii_file{fname, fd, true};
if (fstat(ret.fd, &ret.st) == -1) {
@@ -135,12 +119,6 @@ auto raii_file::mkstemp(const char *pattern, int flags, int perms) -> tl::expect
return tl::make_unexpected(fmt::format("cannot create file {}: {}", pattern, ::strerror(errno)));
}
- if (!rspamd_file_lock(fd, TRUE)) {
- close(fd);
- (void)unlink(mutable_pattern.c_str());
- return tl::make_unexpected(fmt::format("cannot lock file {}: {}", pattern, ::strerror(errno)));
- }
-
auto ret = raii_file{mutable_pattern.c_str(), fd, true};
if (fstat(ret.fd, &ret.st) == -1) {
@@ -157,11 +135,15 @@ raii_file::~raii_file() noexcept
if (temp) {
(void)unlink(fname.c_str());
}
- (void) rspamd_file_unlock(fd, FALSE);
close(fd);
}
}
+auto raii_file::update_stat() noexcept -> bool
+{
+ return fstat(fd, &st) != -1;
+}
+
raii_locked_file::~raii_locked_file() noexcept
{
@@ -197,6 +179,8 @@ auto raii_mmaped_file::mmap_shared(raii_file &&file,
{
void *map;
+ /* Update stat on file to ensure it is up-to-date */
+ file.update_stat();
map = mmap(NULL, file.get_stat().st_size, flags, MAP_SHARED, file.get_fd(), 0);
if (map == MAP_FAILED) {
@@ -386,6 +370,36 @@ TEST_CASE("tempfile") {
CHECK(serrno == ENOENT);
}
+TEST_CASE("mmap") {
+ std::string tmpname;
+ {
+ auto raii_file = raii_file::mkstemp("/tmp//doctest-XXXXXXXX",
+ O_RDWR|O_CREAT|O_EXCL, 00600);
+ CHECK(raii_file.has_value());
+ CHECK(raii_file->get_dir() == "/tmp");
+ CHECK(access(raii_file->get_name().data(), R_OK) == 0);
+ tmpname = std::string{raii_file->get_name()};
+ char payload[] = {'1', '2', '3'};
+ CHECK(write(raii_file->get_fd(), payload, sizeof(payload)) == sizeof(payload));
+ auto mmapped_file1 = raii_mmaped_file::mmap_shared(std::move(raii_file.value()), PROT_READ|PROT_WRITE);
+ CHECK(mmapped_file1.has_value());
+ CHECK(!raii_file->is_valid());
+ CHECK(mmapped_file1->get_size() == sizeof(payload));
+ CHECK(memcmp(mmapped_file1->get_map(), payload, sizeof(payload)) == 0);
+ *(char *)mmapped_file1->get_map() = '2';
+ auto mmapped_file2 = raii_mmaped_file::mmap_shared(tmpname.c_str(), O_RDONLY, PROT_READ);
+ CHECK(mmapped_file2.has_value());
+ CHECK(mmapped_file2->get_size() == sizeof(payload));
+ CHECK(memcmp(mmapped_file2->get_map(), payload, sizeof(payload)) != 0);
+ CHECK(memcmp(mmapped_file2->get_map(), mmapped_file1->get_map(), sizeof(payload)) == 0);
+ }
+ // File must be deleted after this call
+ auto ret = ::access(tmpname.c_str(), R_OK);
+ auto serrno = errno;
+ CHECK(ret == -1);
+ CHECK(serrno == ENOENT);
+}
+
} // TEST_SUITE
} // namespace tests
diff --git a/src/libutil/cxx/locked_file.hxx b/src/libutil/cxx/locked_file.hxx
index c7d286cbb..507b02762 100644
--- a/src/libutil/cxx/locked_file.hxx
+++ b/src/libutil/cxx/locked_file.hxx
@@ -44,6 +44,10 @@ public:
return st;
};
+ auto get_size() const -> std::size_t {
+ return st.st_size;
+ };
+
auto get_name() const -> std::string_view {
return std::string_view{fname};
}
@@ -93,10 +97,24 @@ public:
*this = std::move(other);
}
+ /**
+ * Prevent file from being deleted
+ * @return
+ */
auto make_immortal() noexcept {
temp = false;
}
+ /**
+ * Performs fstat on an opened file to refresh internal stat
+ * @return
+ */
+ auto update_stat() noexcept -> bool;
+
+ auto is_valid() noexcept -> bool {
+ return fd != -1;
+ }
+
/* Do not allow copy/default ctor */
const raii_file& operator=(const raii_file &other) = delete;
raii_file() = delete;
@@ -181,6 +199,7 @@ struct raii_mmaped_file final {
static auto mmap_shared(const char *fname, int open_flags, int mmap_flags) -> tl::expected<raii_mmaped_file, std::string>;
// Returns a constant pointer to the underlying map
auto get_map() const -> void* {return map;}
+ auto get_file() const -> const raii_file& { return file; }
// Passes the ownership of the mmaped memory to the callee
auto steal_map() -> std::tuple<void *, std::size_t> {
auto ret = std::make_tuple(this->map, file.get_stat().st_size);
More information about the Commits
mailing list