commit 4b6706a: [Minor] Also allow mmaps to be RAII protected
Vsevolod Stakhov
vsevolod at rspamd.com
Sat Apr 30 19:21:09 UTC 2022
Author: Vsevolod Stakhov
Date: 2022-04-02 13:33:10 +0100
URL: https://github.com/rspamd/rspamd/commit/4b6706a6955b111fb9366fdea2f87c81a9d2edd1
[Minor] Also allow mmaps to be RAII protected
---
src/libutil/cxx/locked_file.cxx | 54 ++++++++++++++++++++++++++++++++++-
src/libutil/cxx/locked_file.hxx | 63 +++++++++++++++++++++++++++++++++++++++++
2 files changed, 116 insertions(+), 1 deletion(-)
diff --git a/src/libutil/cxx/locked_file.cxx b/src/libutil/cxx/locked_file.cxx
index 8bbb51bf3..9d47304a9 100644
--- a/src/libutil/cxx/locked_file.cxx
+++ b/src/libutil/cxx/locked_file.cxx
@@ -7,6 +7,8 @@
#include "libutil/util.h"
#include "libutil/unix-std.h"
+namespace rspamd::util {
+
auto raii_locked_file::open(const char *fname, int flags) -> tl::expected<raii_locked_file, std::string>
{
int oflags = flags;
@@ -24,7 +26,13 @@ auto raii_locked_file::open(const char *fname, int flags) -> tl::expected<raii_l
return tl::make_unexpected(fmt::format("cannot lock file {}: {}", fname, ::strerror(errno)));
}
- return raii_locked_file{fd};
+ auto ret = raii_locked_file{fd};
+
+ if (fstat(ret.fd, &ret.st) == -1) {
+ return tl::make_unexpected(fmt::format("cannot stat file {}: {}", fname, ::strerror(errno)));
+ }
+
+ return ret;
}
raii_locked_file::~raii_locked_file()
@@ -34,3 +42,47 @@ raii_locked_file::~raii_locked_file()
close(fd);
}
}
+
+raii_mmaped_locked_file::raii_mmaped_locked_file(raii_locked_file &&_file, void *_map)
+ : file(std::move(_file)), map(_map) {}
+
+auto raii_mmaped_locked_file::mmap_shared(raii_locked_file &&file,
+ int flags) -> tl::expected<raii_mmaped_locked_file, std::string>
+{
+ void *map;
+
+ map = mmap(NULL, file.get_stat().st_size, flags, MAP_SHARED, file.get_fd(), 0);
+
+ if (map == MAP_FAILED) {
+ return tl::make_unexpected(fmt::format("cannot mmap file at fd: {}: {}",
+ file.get_fd(), ::strerror(errno)));
+
+ }
+
+ return raii_mmaped_locked_file{std::move(file), map};
+}
+
+auto raii_mmaped_locked_file::mmap_shared(const char *fname, int open_flags,
+ int mmap_flags) -> tl::expected<raii_mmaped_locked_file, std::string>
+{
+ auto file = raii_locked_file::open(fname, open_flags);
+
+ if (!file.has_value()) {
+ return tl::make_unexpected(file.error());
+ }
+
+ return raii_mmaped_locked_file::mmap_shared(std::move(file.value()), mmap_flags);
+}
+
+raii_mmaped_locked_file::~raii_mmaped_locked_file()
+{
+ munmap(map, file.get_stat().st_size);
+}
+
+raii_mmaped_locked_file::raii_mmaped_locked_file(raii_mmaped_locked_file &&other) noexcept
+ : file(std::move(other.file))
+{
+ std::swap(map, other.map);
+}
+
+}
diff --git a/src/libutil/cxx/locked_file.hxx b/src/libutil/cxx/locked_file.hxx
index 63239fcd9..712c75a19 100644
--- a/src/libutil/cxx/locked_file.hxx
+++ b/src/libutil/cxx/locked_file.hxx
@@ -19,17 +19,80 @@
#include "contrib/expected/expected.hpp"
#include <string>
+#include <sys/stat.h>
+namespace rspamd::util {
/**
* A simple RAII object to contain a file descriptor with an flock wrap
* A file is unlocked and closed when not needed
*/
struct raii_locked_file final {
~raii_locked_file();
+
static auto open(const char *fname, int flags) -> tl::expected<raii_locked_file, std::string>;
+
+ auto get_fd() const -> int
+ {
+ return fd;
+ }
+
+ auto get_stat() const -> const struct stat&
+ {
+ return st;
+ };
+
+ raii_locked_file& operator=(raii_locked_file &&other) noexcept {
+ std::swap(fd, other.fd);
+ std::swap(st, other.st);
+
+ return *this;
+ }
+
+ raii_locked_file(raii_locked_file &&other) noexcept {
+ *this = std::move(other);
+ }
+
+ /* Do not allow copy/default ctor */
+ const raii_locked_file& operator=(const raii_locked_file &other) = delete;
+ raii_locked_file() = delete;
+ raii_locked_file(const raii_locked_file &other) = delete;
private:
int fd;
+ struct stat st;
+
explicit raii_locked_file(int _fd) : fd(_fd) {}
};
+/**
+ * A mmap wrapper on top of a locked file
+ */
+struct raii_mmaped_locked_file final {
+ ~raii_mmaped_locked_file();
+ static auto mmap_shared(raii_locked_file &&file, int flags) -> tl::expected<raii_mmaped_locked_file, std::string>;
+ static auto mmap_shared(const char *fname, int open_flags, int mmap_flags) -> tl::expected<raii_mmaped_locked_file, std::string>;
+ auto get_map() const -> void* {return map;}
+ auto get_size() const -> std::size_t { return file.get_stat().st_size; }
+
+ raii_mmaped_locked_file& operator=(raii_mmaped_locked_file &&other) noexcept {
+ std::swap(map, other.map);
+ file = std::move(other.file);
+
+ return *this;
+ }
+
+ raii_mmaped_locked_file(raii_mmaped_locked_file &&other) noexcept;
+
+ /* Do not allow copy/default ctor */
+ const raii_mmaped_locked_file& operator=(const raii_mmaped_locked_file &other) = delete;
+ raii_mmaped_locked_file() = delete;
+ raii_mmaped_locked_file(const raii_mmaped_locked_file &other) = delete;
+private:
+ /* Is intended to be used with map_shared */
+ explicit raii_mmaped_locked_file(raii_locked_file &&_file, void *_map);
+ raii_locked_file file;
+ void *map{};
+};
+
+}
+
#endif //RSPAMD_LOCKED_FILE_HXX
More information about the Commits
mailing list