diff --git a/src/io.h b/src/io.h index a68795591..ec9af69cf 100644 --- a/src/io.h +++ b/src/io.h @@ -170,127 +170,11 @@ class separated_buffer_t : noncopyable_t { /// Describes what type of IO operation an io_data_t represents. enum class io_mode_t { file, pipe, fd, close, bufferfill }; -/// Represents an FD redirection. -class io_data_t : noncopyable_t, nonmovable_t { - protected: - io_data_t(io_mode_t m, int fd, int source_fd) : io_mode(m), fd(fd), source_fd(source_fd) {} - - public: - /// Type of redirect. - const io_mode_t io_mode; - - /// FD to redirect. - const int fd; - - /// Source fd. This is dup2'd to fd, or if it is -1, then fd is closed. - /// That is, we call dup2(source_fd, fd). - const int source_fd; - - virtual void print() const = 0; - virtual ~io_data_t() = 0; -}; - -class io_close_t final : public io_data_t { - public: - explicit io_close_t(int f) : io_data_t(io_mode_t::close, f, -1) {} - - void print() const override; - ~io_close_t() override; -}; - -class io_fd_t final : public io_data_t { - public: - void print() const override; - - ~io_fd_t() override; - - /// fd to redirect specified fd to. For example, in 2>&1, source_fd is 1, and io_data_t::fd - /// is 2. - io_fd_t(int f, int source_fd) : io_data_t(io_mode_t::fd, f, source_fd) {} -}; - -/// Represents a redirection to or from an opened file. -class io_file_t final : public io_data_t { - public: - void print() const override; - - io_file_t(int fd, autoclose_fd_t file) - : io_data_t(io_mode_t::file, fd, file.fd()), file_fd_(std::move(file)) { - // Invalid file redirections are replaced with a closed fd, so the following - // assertion isn't guaranteed to pass: - // assert(file_fd_.valid() && "File is not valid"); - } - - ~io_file_t() override; - - private: - // The fd for the file which we are writing to or reading from. - autoclose_fd_t file_fd_; -}; - -/// Represents (one end) of a pipe. -class io_pipe_t final : public io_data_t { - // The pipe's fd. Conceptually this is dup2'd to io_data_t::fd. - autoclose_fd_t pipe_fd_; - - /// Whether this is an input pipe. This is used only for informational purposes. - const bool is_input_; - - public: - void print() const override; - - io_pipe_t(int fd, bool is_input, autoclose_fd_t pipe_fd) - : io_data_t(io_mode_t::pipe, fd, pipe_fd.fd()), - pipe_fd_(std::move(pipe_fd)), - is_input_(is_input) { - assert(pipe_fd_.valid() && "Pipe is not valid"); - } - - ~io_pipe_t() override; -}; - class io_buffer_t; -/// Represents filling an io_buffer_t. Very similar to io_pipe_t. -class io_bufferfill_t final : public io_data_t { - /// Write end. The other end is connected to an io_buffer_t. - const autoclose_fd_t write_fd_; - - /// The receiving buffer. - const std::shared_ptr buffer_; - - public: - void print() const override; - - // The ctor is public to support make_shared() in the static create function below. - // Do not invoke this directly. - io_bufferfill_t(int target, autoclose_fd_t write_fd, std::shared_ptr buffer) - : io_data_t(io_mode_t::bufferfill, target, write_fd.fd()), - write_fd_(std::move(write_fd)), - buffer_(std::move(buffer)) { - assert(write_fd_.valid() && "fd is not valid"); - } - - ~io_bufferfill_t() override; - - std::shared_ptr buffer() const { return buffer_; } - - /// Create an io_bufferfill_t which, when written from, fills a buffer with the contents. - /// \returns nullptr on failure, e.g. too many open fds. - /// - /// \param target the fd which this will be dup2'd to - typically stdout. - static shared_ptr create(size_t buffer_limit = 0, int target = STDOUT_FILENO); - - /// Reset the receiver (possibly closing the write end of the pipe), and complete the fillthread - /// of the buffer. \return the buffer. - static separated_buffer_t finish(std::shared_ptr &&filler); -}; - struct callback_args_t; struct autoclose_fd_t2; -using io_data_ref_t = std::shared_ptr; - using io_chain_t = IoChain; dup2_list_t dup2_list_resolve_chain_shim(const io_chain_t &io_chain);