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