From 9870b77f9000c55bbe507bbb11d6d20fac2e8da0 Mon Sep 17 00:00:00 2001 From: Tavian Barnes Date: Thu, 15 Apr 2021 14:34:55 -0400 Subject: util: Tweak the safe read/write functions --- bar.c | 2 +- spawn.c | 8 ++++---- util.c | 71 ++++++++++++++++++++++++++++------------------------------------- util.h | 27 ++++++++++++------------- 4 files changed, 49 insertions(+), 59 deletions(-) diff --git a/bar.c b/bar.c index 33127f8..31734ac 100644 --- a/bar.c +++ b/bar.c @@ -58,7 +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); - return safe_write_all(fd, str, len) == (ssize_t)len ? 0 : -1; + return xwrite(fd, str, len) == len ? 0 : -1; } /** Number of decimal digits needed for terminal sizes. */ diff --git a/spawn.c b/spawn.c index 0a260dc..094214b 100644 --- a/spawn.c +++ b/spawn.c @@ -189,9 +189,9 @@ static void bfs_spawn_exec(const char *exe, const struct bfs_spawn *ctx, char ** fail: error = errno; - // In case of write error parent will still see that we exited - // unsuccessfully, but won't know why. - (void) safe_write_all(pipefd[1], &error, sizeof(error)); + // In case of a write error, the parent will still see that we exited + // unsuccessfully, but won't know why + (void) xwrite(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_all(pipefd[0], &error, sizeof(error)); + ssize_t nbytes = xread(pipefd[0], &error, sizeof(error)); close(pipefd[0]); if (nbytes == sizeof(error)) { int wstatus; diff --git a/util.c b/util.c index 00f5b78..19656e9 100644 --- a/util.c +++ b/util.c @@ -369,57 +369,48 @@ int bfs_minor(dev_t dev) { #endif } -ssize_t safe_read(int fd, void *buf, size_t nbytes) { - for (;;) { - ssize_t ret = read(fd, buf, nbytes); - if (ret < 0 && errno == EINTR) { - continue; - } - return ret; - } -} - -ssize_t safe_read_all(int fd, void *buf, size_t nbytes) { +size_t xread(int fd, void *buf, size_t nbytes) { size_t count = 0; - for (;;) { + + while (count < nbytes) { 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; + if (errno == EINTR) { + continue; + } else { + break; + } + } else if (ret == 0) { + // EOF + errno = 0; + break; + } else { + count += ret; } } -} -ssize_t safe_write(int fd, const void *buf, size_t nbytes) { - for (;;) { - ssize_t ret = write(fd, buf, nbytes); - if (ret < 0 && errno == EINTR) { - continue; - } - return ret; - } + return count; } -ssize_t safe_write_all(int fd, const void *buf, size_t nbytes) -{ +size_t xwrite(int fd, const void *buf, size_t nbytes) { size_t count = 0; - for (;;) { + + while (count < nbytes) { 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; + if (errno == EINTR) { + continue; + } else { + break; + } + } else if (ret == 0) { + // EOF? + errno = 0; + break; + } else { + count += ret; } } + + return count; } diff --git a/util.h b/util.h index 7293d50..1b52513 100644 --- a/util.h +++ b/util.h @@ -226,23 +226,22 @@ int bfs_major(dev_t dev); int bfs_minor(dev_t dev); /** - * A safe version of read() that handles interrupted system calls. - */ -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. + * A safe version of read() that handles interrupted system calls and partial + * reads. + * + * @return + * The number of bytes read. A value != nbytes indicates an error + * (errno != 0) or end of file (errno == 0). */ -ssize_t safe_write(int fd, const void *buf, size_t nbytes); +size_t xread(int fd, void *buf, size_t nbytes); /** - * A safe version of write() that handles interrupted system calls and partial writes. + * A safe version of write() that handles interrupted system calls and partial + * writes. + * + * @return + The number of bytes written. A value != nbytes indicates an error. */ -ssize_t safe_write_all(int fd, const void *buf, size_t nbytes); +size_t xwrite(int fd, const void *buf, size_t nbytes); #endif // BFS_UTIL_H -- cgit v1.2.3