return raii_file{static_cast<raii_file&&>(std::move(*this))};
}
-raii_mmaped_file::raii_mmaped_file(raii_file &&_file, void *_map)
- : file(std::move(_file)), map(_map)
+raii_mmaped_file::raii_mmaped_file(raii_file &&file, void *map, std::size_t sz)
+ : file(std::move(file)), map(map), map_size(sz)
{
}
auto raii_mmaped_file::mmap_shared(raii_file &&file,
- int flags) -> tl::expected<raii_mmaped_file, error>
+ int flags, std::int64_t offset) -> tl::expected<raii_mmaped_file, error>
{
void *map;
+ if (file.get_stat().st_size < offset || offset < 0) {
+ return tl::make_unexpected(error {
+ fmt::format("cannot mmap file {} due to incorrect offset; offset={}, size={}",
+ file.get_name(), offset, file.get_size()), EINVAL});
+ }
/* 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);
+ map = mmap(nullptr, file.get_size() - offset, flags, MAP_SHARED, file.get_fd(), offset);
if (map == MAP_FAILED) {
- return tl::make_unexpected(error { fmt::format("cannot mmap file at fd: {}: {}",
- file.get_fd(), ::strerror(errno)), errno });
+ return tl::make_unexpected(error { fmt::format("cannot mmap file {}: {}",
+ file.get_name(), ::strerror(errno)), errno });
}
- return raii_mmaped_file{std::move(file), map};
+ return raii_mmaped_file{std::move(file), map, file.get_size() - offset};
}
auto raii_mmaped_file::mmap_shared(const char *fname, int open_flags,
- int mmap_flags) -> tl::expected<raii_mmaped_file, error>
+ int mmap_flags, std::int64_t offset) -> tl::expected<raii_mmaped_file, error>
{
auto file = raii_file::open(fname, open_flags);
return tl::make_unexpected(file.error());
}
- return raii_mmaped_file::mmap_shared(std::move(file.value()), mmap_flags);
+ return raii_mmaped_file::mmap_shared(std::move(file.value()), mmap_flags, offset);
}
raii_mmaped_file::~raii_mmaped_file()
{
if (map != nullptr) {
- munmap(map, file.get_stat().st_size);
+ munmap(map, map_size);
}
}
: file(std::move(other.file))
{
std::swap(map, other.map);
+ std::swap(map_size, other.map_size);
}
auto raii_file_sink::create(const char *fname, int flags, int perms,
*/
struct raii_mmaped_file final {
~raii_mmaped_file();
- static auto mmap_shared(raii_file &&file, int flags) -> tl::expected<raii_mmaped_file, error>;
- static auto mmap_shared(const char *fname, int open_flags, int mmap_flags) -> tl::expected<raii_mmaped_file, error>;
+ static auto mmap_shared(raii_file &&file, int flags, std::int64_t offset = 0) -> tl::expected<raii_mmaped_file, error>;
+ static auto mmap_shared(const char *fname, int open_flags, int mmap_flags, std::int64_t offset = 0) -> tl::expected<raii_mmaped_file, error>;
// 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);
+ auto ret = std::make_tuple(this->map, map_size);
this->map = nullptr;
return ret;
}
raii_mmaped_file& operator=(raii_mmaped_file &&other) noexcept {
std::swap(map, other.map);
+ std::swap(map_size, other.map_size);
file = std::move(other.file);
return *this;
raii_mmaped_file(const raii_mmaped_file &other) = delete;
private:
/* Is intended to be used with map_shared */
- explicit raii_mmaped_file(raii_file &&_file, void *_map);
+ explicit raii_mmaped_file(raii_file &&_file, void *_map, std::size_t sz);
raii_file file;
void *map = nullptr;
+ std::size_t map_size;
};
/**