From 3dad2125b9048fdc3790d3e7c4770f7174be889c Mon Sep 17 00:00:00 2001 From: "Markus F.X.J. Oberhumer" Date: Thu, 15 Apr 2021 18:37:32 +0200 Subject: util: add safe_read_all() and safe_write_all() functions. --- bar.c | 12 +----------- spawn.c | 4 ++-- util.c | 35 +++++++++++++++++++++++++++++++++++ util.h | 10 ++++++++++ 4 files changed, 48 insertions(+), 13 deletions(-) diff --git a/bar.c b/bar.c index 67f5d6e..33127f8 100644 --- a/bar.c +++ b/bar.c @@ -58,17 +58,7 @@ static int bfs_bar_getsize(struct bfs_bar *bar) { /** Async Signal Safe puts(). */ static int ass_puts(int fd, const char *str) { size_t len = strlen(str); - - while (len > 0) { - ssize_t ret = safe_write(fd, str, len); - if (ret <= 0) { - return -1; - } - str += ret; - len -= ret; - } - - return 0; + return safe_write_all(fd, str, len) == (ssize_t)len ? 0 : -1; } /** Number of decimal digits needed for terminal sizes. */ diff --git a/spawn.c b/spawn.c index 5878122..0a260dc 100644 --- a/spawn.c +++ b/spawn.c @@ -191,7 +191,7 @@ fail: // In case of write error parent will still see that we exited // unsuccessfully, but won't know why. - safe_write(pipefd[1], &error, sizeof(error)); + (void) safe_write_all(pipefd[1], &error, sizeof(error)); close(pipefd[1]); _Exit(127); @@ -221,7 +221,7 @@ pid_t bfs_spawn(const char *exe, const struct bfs_spawn *ctx, char **argv, char // Parent close(pipefd[1]); - ssize_t nbytes = safe_read(pipefd[0], &error, sizeof(error)); + ssize_t nbytes = safe_read_all(pipefd[0], &error, sizeof(error)); close(pipefd[0]); if (nbytes == sizeof(error)) { int wstatus; diff --git a/util.c b/util.c index 611d4b5..00f5b78 100644 --- a/util.c +++ b/util.c @@ -379,6 +379,23 @@ ssize_t safe_read(int fd, void *buf, size_t nbytes) { } } +ssize_t safe_read_all(int fd, void *buf, size_t nbytes) { + size_t count = 0; + for (;;) { + ssize_t ret = read(fd, (char *)buf + count, nbytes - count); + if (ret < 0 && errno == EINTR) { + continue; + } + if (ret < 0) { + return ret; // always return error < 0 + } + count += ret; + if (ret == 0 || count == nbytes) { // EOF or success + return count; + } + } +} + ssize_t safe_write(int fd, const void *buf, size_t nbytes) { for (;;) { ssize_t ret = write(fd, buf, nbytes); @@ -388,3 +405,21 @@ ssize_t safe_write(int fd, const void *buf, size_t nbytes) { return ret; } } + +ssize_t safe_write_all(int fd, const void *buf, size_t nbytes) +{ + size_t count = 0; + for (;;) { + ssize_t ret = write(fd, (const char *)buf + count, nbytes - count); + if (ret < 0 && errno == EINTR) { + continue; + } + if (ret < 0) { + return ret; // always return error < 0 + } + count += ret; + if (ret == 0 || count == nbytes) { // EOF (should never happen with write) or success + return count; + } + } +} diff --git a/util.h b/util.h index ef67566..7293d50 100644 --- a/util.h +++ b/util.h @@ -230,9 +230,19 @@ int bfs_minor(dev_t dev); */ ssize_t safe_read(int fd, void *buf, size_t nbytes); +/** + * A safe version of read() that handles interrupted system calls and partial reads. + */ +ssize_t safe_read_all(int fd, void *buf, size_t nbytes); + /** * A safe version of write() that handles interrupted system calls. */ ssize_t safe_write(int fd, const void *buf, size_t nbytes); +/** + * A safe version of write() that handles interrupted system calls and partial writes. + */ +ssize_t safe_write_all(int fd, const void *buf, size_t nbytes); + #endif // BFS_UTIL_H -- cgit v1.2.3