]> git.ipfire.org Git - thirdparty/rspamd.git/commitdiff
[Minor] Also allow mmaps to be RAII protected
authorVsevolod Stakhov <vsevolod@rspamd.com>
Sat, 2 Apr 2022 12:33:10 +0000 (13:33 +0100)
committerVsevolod Stakhov <vsevolod@rspamd.com>
Sat, 2 Apr 2022 12:33:10 +0000 (13:33 +0100)
src/libutil/cxx/locked_file.cxx
src/libutil/cxx/locked_file.hxx

index 8bbb51bf3048492856676f50d856c63d14c1c776..9d47304a99b15b3ae6159519f493449988518b96 100644 (file)
@@ -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);
+}
+
+}
index 63239fcd9346cf7e6fd9b48acc1cc538b4aefa2b..712c75a19e15087f26044a9550b1c5c3da212038 100644 (file)
 
 #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