>From f5d31e13265fda65017145f9206d634d6715cded Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C3=A1draig=20Brady?= Date: Mon, 9 Mar 2015 23:58:25 +0000 Subject: [PATCH] tee: avoid using stdio as tee doesn't buffer * src/tee.c (tee_files): Since tee doesn't buffer, avoid using stdio streams and just the lower level fd interface. Since we'd disabled buffering in stdio, this is not a significant optimization. --- src/tee.c | 37 ++++++++++++++++--------------------- 1 file changed, 16 insertions(+), 21 deletions(-) diff --git a/src/tee.c b/src/tee.c index 3c39a4a..a0ed3c2 100644 --- a/src/tee.c +++ b/src/tee.c @@ -25,7 +25,7 @@ #include "argmatch.h" #include "error.h" #include "fadvise.h" -#include "stdio--.h" +#include "full-write.h" #include "xfreopen.h" /* The official name of this program (e.g., no 'g' prefix). */ @@ -182,15 +182,16 @@ static bool tee_files (int nfiles, const char **files) { size_t n_outputs = 0; - FILE **descriptors; + int *descriptors; char buffer[BUFSIZ]; ssize_t bytes_read = 0; int i; bool ok = true; - char const *mode_string = - (O_BINARY - ? (append ? "ab" : "wb") - : (append ? "a" : "w")); + int mode = O_WRONLY | O_CREAT | O_BINARY; + if (append) + mode |= O_APPEND; + else + mode |= O_TRUNC; descriptors = xnmalloc (nfiles + 1, sizeof *descriptors); @@ -208,16 +209,15 @@ tee_files (int nfiles, const char **files) /* In the array of NFILES + 1 descriptors, make the first one correspond to standard output. */ - descriptors[0] = stdout; + descriptors[0] = STDOUT_FILENO; files[0] = _("standard output"); - setvbuf (stdout, NULL, _IONBF, 0); n_outputs++; for (i = 1; i <= nfiles; i++) { /* Do not treat "-" specially - as mandated by POSIX. */ - descriptors[i] = fopen (files[i], mode_string); - if (descriptors[i] == NULL) + descriptors[i] = open (files[i], mode, 0666); + if (descriptors[i] == -1) { error (output_error == output_error_exit || output_error == output_error_exit_nopipe, @@ -225,15 +225,12 @@ tee_files (int nfiles, const char **files) ok = false; } else - { - setvbuf (descriptors[i], NULL, _IONBF, 0); - n_outputs++; - } + n_outputs++; } while (n_outputs) { - bytes_read = read (0, buffer, sizeof buffer); + bytes_read = read (STDIN_FILENO, buffer, sizeof buffer); if (bytes_read < 0 && errno == EINTR) continue; if (bytes_read <= 0) @@ -242,21 +239,19 @@ tee_files (int nfiles, const char **files) /* Write to all NFILES + 1 descriptors. Standard output is the first one. */ for (i = 0; i <= nfiles; i++) - if (descriptors[i] - && fwrite (buffer, bytes_read, 1, descriptors[i]) != 1) + if (descriptors[i] != -1 + && full_write (descriptors[i], buffer, bytes_read) != bytes_read) { int w_errno = errno; bool fail = errno != EPIPE || (output_error == output_error_exit || output_error == output_error_warn); - if (descriptors[i] == stdout) - clearerr (stdout); /* Avoid redundant close_stdout diagnostic. */ if (fail) { error (output_error == output_error_exit || output_error == output_error_exit_nopipe, w_errno, "%s", files[i]); } - descriptors[i] = NULL; + descriptors[i] = -1; if (fail) ok = false; n_outputs--; @@ -271,7 +266,7 @@ tee_files (int nfiles, const char **files) /* Close the files, but not standard output. */ for (i = 1; i <= nfiles; i++) - if (descriptors[i] && fclose (descriptors[i]) != 0) + if (descriptors[i] != -1 && close (descriptors[i]) != 0) { error (0, errno, "%s", files[i]); ok = false; -- 2.1.0