From b31bcf598b7129d97c5817dce25791748bc2534a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Franti=C5=A1ek=20Boh=C3=A1=C4=8Dek?= Date: Mon, 14 Jun 2021 21:33:37 +0200 Subject: [PATCH] feat: add nonblocking io functions --- image-viewer/include/nonblocking_io.h | 14 +++++ image-viewer/src/nonblocking_io.c | 86 +++++++++++++++++++++++++++ 2 files changed, 100 insertions(+) create mode 100644 image-viewer/include/nonblocking_io.h create mode 100644 image-viewer/src/nonblocking_io.c diff --git a/image-viewer/include/nonblocking_io.h b/image-viewer/include/nonblocking_io.h new file mode 100644 index 0000000..31913a4 --- /dev/null +++ b/image-viewer/include/nonblocking_io.h @@ -0,0 +1,14 @@ +#ifndef _NONBLOCKING_IO_H +#define _NONBLOCKING_IO_H + +#include +#include +#include +#include + +int file_set_nonblocking(int file, struct termios *old); +int file_set_blocking(int file, struct termios *old); +int file_read_nonblocking(int file, size_t max_size, uint8_t *data); +bool file_write_nonblocking(int file, size_t size, uint8_t *data, int max_delay); + +#endif //_NONBLOCKING_IO_H diff --git a/image-viewer/src/nonblocking_io.c b/image-viewer/src/nonblocking_io.c new file mode 100644 index 0000000..4cc4761 --- /dev/null +++ b/image-viewer/src/nonblocking_io.c @@ -0,0 +1,86 @@ +#include "nonblocking_io.h" +#include "time_measure.h" +#include +#include +#include +#include +#include +#include +#include +#include + +int file_set_blocking(int file, struct termios *old) { + int oldfl; + oldfl = fcntl(file, F_GETFL); + if (oldfl == -1) { + return oldfl; + } + + if(tcsetattr(file, TCSANOW, old) == -1) { + return -1; + } + + return fcntl(file, F_SETFL, oldfl & ~O_NONBLOCK); +} + +int file_set_nonblocking(int file, struct termios *old) +{ + fcntl(file, F_SETFL, O_NONBLOCK); + + struct termios attrs; + if (tcgetattr(file, &attrs) < 0) { + return -1; + } + + if (old != NULL) { + tcgetattr(file, old); + } + + cfmakeraw(&attrs); + + tcsetattr(file, TCSANOW, &attrs); + return 1; +} + +int file_read_nonblocking(int file, size_t max_size, uint8_t *data) +{ + int read_bytes = read(file, data, max_size); + + int error = errno; + if (read_bytes == -1 && error == EAGAIN) { + read_bytes = 0; // Do not treat EAGAIN as an error. + } else { + errno = error; + } + + return read_bytes; +} + +bool file_write_nonblocking(int file, size_t size, uint8_t *data, int max_delay) { + int written = 0; + bool correct = true; + + TimeMeasure measure = tmeasure_start(); + + while (written < size && !tmeasure_exceededmilli(&measure, max_delay)) { + int status = write(file, data + written, size - written); + + if (status == -1) { + int error = errno; + + if (error != EAGAIN) { + errno = error; + correct = false; + break; + } + } else { + written += status; + } + } + + if (correct && written < size) { + errno = ETIMEDOUT; + } + + return correct; +} -- 2.49.0