blob: 1c53258aaaa3ba0043c7143ed65afeb95df844e6 [file] [log] [blame]
// Copyright 2022 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef SRC_LIB_ELFLDLTL_INCLUDE_LIB_ELFLDLTL_FD_H_
#define SRC_LIB_ELFLDLTL_INCLUDE_LIB_ELFLDLTL_FD_H_
#include <lib/fit/result.h>
#include <lib/stdcompat/span.h>
#include <unistd.h>
#include <cerrno>
#include <fbl/unique_fd.h>
#include "file.h"
#include "posix.h"
namespace elfldltl {
// elfldltl::UniqueFdFile is constructible from fbl::unique_fd and meets the
// File API (see <lib/elfldltl/memory.h>) by calling pread. The same thing
// for unowned plain `int` file descriptors is provided by elfldltl::FdFile.
namespace internal {
inline fit::result<PosixError> ReadFd(int fd, off_t offset, cpp20::span<std::byte> buffer) {
do {
ssize_t n = pread(fd, buffer.data(), buffer.size(), offset);
if (n < 0) {
return fit::error{PosixError{errno}};
}
if (n == 0) {
return fit::error{PosixError{}}; // This signifies EOF.
}
buffer = buffer.subspan(static_cast<size_t>(n));
offset += n;
} while (!buffer.empty());
return fit::ok();
}
inline int MakeInvalidFd() { return -1; }
inline fit::result<PosixError> ReadUniqueFd(const fbl::unique_fd& fd, off_t offset,
cpp20::span<std::byte> buffer) {
return ReadFd(fd.get(), offset, buffer);
}
} // namespace internal
template <class Diagnostics>
using FdFileBase = File<Diagnostics, int, off_t, internal::ReadFd, internal::MakeInvalidFd>;
template <class Diagnostics>
using UniqueFdFileBase = File<Diagnostics, fbl::unique_fd, off_t, internal::ReadUniqueFd>;
template <class Diagnostics>
class FdFile : public FdFileBase<Diagnostics> {
public:
using FdFileBase<Diagnostics>::FdFileBase;
FdFile(const FdFile&) noexcept = default;
FdFile(FdFile&&) noexcept = default;
FdFile& operator=(const FdFile&) noexcept = default;
FdFile& operator=(FdFile&&) noexcept = default;
int borrow() const { return this->get(); }
};
// Deduction guide.
template <class Diagnostics>
FdFile(int fd, Diagnostics& diagnostics) -> FdFile<Diagnostics>;
template <class Diagnostics>
FdFile(Diagnostics& diagnostics) -> FdFile<Diagnostics>;
template <class Diagnostics>
class UniqueFdFile : public UniqueFdFileBase<Diagnostics> {
public:
using Base = UniqueFdFileBase<Diagnostics>;
using Base::Base;
UniqueFdFile(UniqueFdFile&&) noexcept = default;
UniqueFdFile& operator=(UniqueFdFile&&) noexcept = default;
int get() const { return Base::get().get(); }
int borrow() const { return get(); }
};
// Deduction guide.
template <class Diagnostics>
UniqueFdFile(fbl::unique_fd fd, Diagnostics& diagnostics) -> UniqueFdFile<Diagnostics>;
template <class Diagnostics>
UniqueFdFile(Diagnostics& diagnostics) -> UniqueFdFile<Diagnostics>;
} // namespace elfldltl
#endif // SRC_LIB_ELFLDLTL_INCLUDE_LIB_ELFLDLTL_FD_H_