iv_fd_pump(3)

πŸ’§ iv_fd_pump β€” bestie's guide to pumping data between file descriptors

okay so this is iv_fd_pump, a page from the ivykis programmer's manual, and it's literally the little helper that moves bytes from one file descriptor to another. no cap, it's giving "glorified pipe but make it event-loop-aware" ✨


🌸 NAME 🌸

IV_FD_PUMP_INIT, iv_fd_pump_init, iv_fd_pump_destroy, iv_fd_pump_pump, iv_fd_pump_is_done β€” pump data between file descriptors πŸ’–


πŸŽ€ SYNOPSIS πŸŽ€

#include <iv_fd_pump.h>

struct iv_fd_pump {
        int             from_fd;
        int             to_fd;
        void            *cookie;
        void            (*set_bands)(void *cookie, int pollin, int pollout);
        unsigned int    flags;
};

void IV_FD_PUMP_INIT(struct iv_fd_pump *this);
void iv_fd_pump_init(struct iv_fd_pump *this);
void iv_fd_pump_destroy(struct iv_fd_pump *this);
int iv_fd_pump_pump(struct iv_fd_pump *this);
int iv_fd_pump_is_done(const struct iv_fd_pump *this);

πŸ¦‹ DESCRIPTION πŸ¦‹

so iv_fd_pump is the way to move data between two file descriptors. that's the whole job bestie, and it eats πŸ’…

setting it up ✨

to get your pump ready to move data, you call IV_FD_PUMP_INIT on a struct iv_fd_pump object, fill in the ->from_fd, ->to_fd, ->cookie, ->set_bands and ->flags members, and then call iv_fd_pump_init on the object. like, in that order. the order matters, i don't make the rules 🫢

tearing it down 🌈

conversely, to destroy a struct iv_fd_pump object, call iv_fd_pump_destroy. and the vibe check here is: there are no restrictions on when this function can be called. whenever. literally whenever. iconic.

actually pumping πŸ”₯

a call to iv_fd_pump_pump will attempt to move data from ->from_fd to ->to_fd via an internal buffer associated with the struct iv_fd_pump object. internal buffer, her own little stash, we love her.

the callback situation πŸ’€

during calls to iv_fd_pump_init, iv_fd_pump_destroy and iv_fd_pump_pump, the callback function specified by ->set_bands may be invoked (with ->cookie as its first argument). that's the pump telling you, through this callback, under which circumstances it wants future invocations of iv_fd_pump_pump to happen. it's not being cryptic on purpose, it's just how it communicates ✨

  • if the pollin argument to ->set_bands is true, there's space left in the internal buffer (and we have not yet seen an end-of-file condition on input), and so you should call iv_fd_pump_pump again when there's a POLLIN condition on ->from_fd. πŸ“₯
  • if the pollout argument to ->set_bands is true, there's data in the internal buffer that could not all be transferred to ->to_fd, and so you should call iv_fd_pump_pump again when there's a POLLOUT condition on ->to_fd. πŸ“€

the relay-eof flag πŸ‘‘

if IV_FD_PUMP_FLAG_RELAY_EOF is set in ->flags, then iv_fd_pump_pump will call shutdown(2) on ->to_fd with SHUT_WR as its second argument upon seeing an end-of-file condition on ->from_fd. and listen β€” but only after all data from the internal buffer has been drained into ->to_fd first. she does not close the door before everyone's out, periodt.

return values of iv_fd_pump_pump 🌟

  • -1 β€” there was an error 😭
  • 0 β€” we're done pumping data, meaning an end-of-file condition was seen on the input file descriptor and all data in the internal buffer has been drained into the output file descriptor. slay, mission accomplished πŸŽ‰
  • 1 β€” there is more data left to be pumped, keep going bestie πŸ”

iv_fd_pump_is_done πŸ’–

iv_fd_pump_is_done will return a true value if iv_fd_pump_pump has previously returned 0. otherwise it will return false. that's it, that's the function, no plot twist.

the tea on how it actually does it β˜•

internally, iv_fd_pump_pump will use splice(2) if it is available. otherwise it will fall back to read(2) and write(2). main character energy with a backup plan, we stan a resilient queen πŸ’…


🧚 SEE ALSO 🧚


ok and that's the whole page, go forth and pump responsibly 🫢

this has been ivykis, dated 2012-06-05 β€” mwah, bye bestie πŸ’œβœ¨