logo

utils-std

Collection of commonly available Unix tools git clone https://anongit.hacktivis.me/git/utils-std.git
commit: cff503f0a83af7a3ba4d6c26cdb5922720ddeabc
parent c368820dca8c75942de33e1ee7e80d284e63bacb
Author: Haelwenn (lanodan) Monnier <contact@hacktivis.me>
Date:   Tue, 10 Sep 2024 09:37:58 +0200

cmd/cat: close stdin/stdout before returning successfully

Inspired by https://blog.sunfishcode.online/errors-from-close/

Diffstat:

Mcmd/cat.c77+++++++++++++++++++++++++++++++++++++++++++++++------------------------------
1 file changed, 47 insertions(+), 30 deletions(-)

diff --git a/cmd/cat.c b/cmd/cat.c @@ -23,7 +23,7 @@ concat(int fd, const char *fdname) while((c = read(fd, buf, sizeof(buf))) > 0) { assert(errno == 0); - if(write(1, buf, (size_t)c) < 0) + if(write(STDOUT_FILENO, buf, (size_t)c) < 0) { fprintf(stderr, "cat: Error writing: %s\n", strerror(errno)); errno = 0; @@ -42,14 +42,14 @@ concat(int fd, const char *fdname) } #ifdef HAS_SPLICE +#define FD_COPY_SPLICE_FLAGS SPLICE_F_MOVE | SPLICE_F_NONBLOCK | SPLICE_F_MORE static int fd_copy(int fd, const char *fdname) { while(1) { assert(errno == 0); - ssize_t ret = - splice(fd, NULL, 1, NULL, SIZE_MAX, SPLICE_F_MOVE | SPLICE_F_NONBLOCK | SPLICE_F_MORE); + ssize_t ret = splice(fd, NULL, STDOUT_FILENO, NULL, SIZE_MAX, FD_COPY_SPLICE_FLAGS); if(ret == 0) break; @@ -112,42 +112,59 @@ main(int argc, char *argv[]) if(argc < 1) { - return fd_copy(0, "<stdin>"); + if(fd_copy(STDIN_FILENO, "<stdin>") != 0) + { + return 1; + } } - - for(int argi = 0; argi < argc; argi++) + else { - if(strncmp(argv[argi], "-", 2) == 0) + for(int argi = 0; argi < argc; argi++) { - if(fd_copy(0, "<stdin>") != 0) + if(strncmp(argv[argi], "-", 2) == 0) { - return 1; + if(fd_copy(STDIN_FILENO, "<stdin>") != 0) + { + return 1; + } } - } - else - { - assert(errno == 0); - int fd = open(argv[argi], O_RDONLY); - if(fd < 0) + else { - fprintf(stderr, "cat: Error opening ‘%s’: %s\n", argv[argi], strerror(errno)); - errno = 0; - return 1; + assert(errno == 0); + int fd = open(argv[argi], O_RDONLY); + if(fd < 0) + { + fprintf(stderr, "cat: Error opening ‘%s’: %s\n", argv[argi], strerror(errno)); + errno = 0; + return 1; + } + + if(fd_copy(fd, argv[argi]) != 0) + { + return 1; + } + + assert(errno == 0); + if(close(fd) < 0) + { + fprintf(stderr, "cat: Error closing ‘%s’: %s\n", argv[argi], strerror(errno)); + errno = 0; + return 1; + } } + } + } - if(fd_copy(fd, argv[argi]) != 0) - { - return 1; - } + if(close(STDIN_FILENO) != 0) + { + fprintf(stderr, "cat: Error closing <stdin>: %s\n", strerror(errno)); + return 1; + } - assert(errno == 0); - if(close(fd) < 0) - { - fprintf(stderr, "cat: Error closing ‘%s’: %s\n", argv[argi], strerror(errno)); - errno = 0; - return 1; - } - } + if(close(STDOUT_FILENO) != 0) + { + fprintf(stderr, "cat: Error closing <stdout>: %s\n", strerror(errno)); + return 1; } return 0;