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:
M | cmd/cat.c | 77 | +++++++++++++++++++++++++++++++++++++++++++++++------------------------------ |
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;