| Absolute File Name: | /home/opencoverage/opencoverage/guest-scripts/coreutils/src/src/libstdbuf.c |
| Source code | Switch to Preprocessed file |
| Line | Source | Count | ||||||
|---|---|---|---|---|---|---|---|---|
| 1 | /* libstdbuf -- a shared lib to preload to setup stdio buffering for a command | - | ||||||
| 2 | Copyright (C) 2009-2018 Free Software Foundation, Inc. | - | ||||||
| 3 | - | |||||||
| 4 | This program is free software: you can redistribute it and/or modify | - | ||||||
| 5 | it under the terms of the GNU General Public License as published by | - | ||||||
| 6 | the Free Software Foundation, either version 3 of the License, or | - | ||||||
| 7 | (at your option) any later version. | - | ||||||
| 8 | - | |||||||
| 9 | This program is distributed in the hope that it will be useful, | - | ||||||
| 10 | but WITHOUT ANY WARRANTY; without even the implied warranty of | - | ||||||
| 11 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | - | ||||||
| 12 | GNU General Public License for more details. | - | ||||||
| 13 | - | |||||||
| 14 | You should have received a copy of the GNU General Public License | - | ||||||
| 15 | along with this program. If not, see <https://www.gnu.org/licenses/>. */ | - | ||||||
| 16 | - | |||||||
| 17 | /* Written by Pádraig Brady. LD_PRELOAD idea from Brian Dessent. */ | - | ||||||
| 18 | - | |||||||
| 19 | #include <config.h> | - | ||||||
| 20 | #include <stdio.h> | - | ||||||
| 21 | #include "system.h" | - | ||||||
| 22 | - | |||||||
| 23 | /* Deactivate config.h's "rpl_"-prefixed definition of malloc, | - | ||||||
| 24 | since we don't link gnulib here, and the replacement isn't | - | ||||||
| 25 | needed in this case as we don't malloc(0). */ | - | ||||||
| 26 | #undef malloc | - | ||||||
| 27 | - | |||||||
| 28 | /* Note currently for glibc (2.3.5) the following call does not change | - | ||||||
| 29 | the buffer size, and more problematically does not give any indication | - | ||||||
| 30 | that the new size request was ignored: | - | ||||||
| 31 | - | |||||||
| 32 | setvbuf (stdout, (char*)NULL, _IOFBF, 8192); | - | ||||||
| 33 | - | |||||||
| 34 | The ISO C99 standard section 7.19.5.6 on the setvbuf function says: | - | ||||||
| 35 | - | |||||||
| 36 | ... If buf is not a null pointer, the array it points to _may_ be used | - | ||||||
| 37 | instead of a buffer allocated by the setvbuf function and the argument | - | ||||||
| 38 | size specifies the size of the array; otherwise, size _may_ determine | - | ||||||
| 39 | the size of a buffer allocated by the setvbuf function. ... | - | ||||||
| 40 | - | |||||||
| 41 | Obviously some interpret the above to mean setvbuf(....,size) | - | ||||||
| 42 | is only a hint from the application which I don't agree with. | - | ||||||
| 43 | - | |||||||
| 44 | FreeBSD's libc seems more sensible in this regard. From the man page: | - | ||||||
| 45 | - | |||||||
| 46 | The size argument may be given as zero to obtain deferred optimal-size | - | ||||||
| 47 | buffer allocation as usual. If it is not zero, then except for | - | ||||||
| 48 | unbuffered files, the buf argument should point to a buffer at least size | - | ||||||
| 49 | bytes long; this buffer will be used instead of the current buffer. (If | - | ||||||
| 50 | the size argument is not zero but buf is NULL, a buffer of the given size | - | ||||||
| 51 | will be allocated immediately, and released on close. This is an extension | - | ||||||
| 52 | to ANSI C; portable code should use a size of 0 with any NULL buffer.) | - | ||||||
| 53 | -------------------- | - | ||||||
| 54 | Another issue is that on glibc-2.7 the following doesn't buffer | - | ||||||
| 55 | the first write if it's greater than 1 byte. | - | ||||||
| 56 | - | |||||||
| 57 | setvbuf(stdout,buf,_IOFBF,127); | - | ||||||
| 58 | - | |||||||
| 59 | Now the POSIX standard says that "allocating a buffer of size bytes does | - | ||||||
| 60 | not necessarily imply that all of size bytes are used for the buffer area". | - | ||||||
| 61 | However I think it's just a buggy implementation due to the various | - | ||||||
| 62 | inconsistencies with write sizes and subsequent writes. */ | - | ||||||
| 63 | - | |||||||
| 64 | static const char * | - | ||||||
| 65 | fileno_to_name (const int fd) | - | ||||||
| 66 | { | - | ||||||
| 67 | const char *ret = NULL; | - | ||||||
| 68 | - | |||||||
| 69 | switch (fd) | - | ||||||
| 70 | { | - | ||||||
| 71 | case 0: never executed: case 0: | 0 | ||||||
| 72 | ret = "stdin"; | - | ||||||
| 73 | break; never executed: break; | 0 | ||||||
| 74 | case 1: never executed: case 1: | 0 | ||||||
| 75 | ret = "stdout"; | - | ||||||
| 76 | break; never executed: break; | 0 | ||||||
| 77 | case 2: never executed: case 2: | 0 | ||||||
| 78 | ret = "stderr"; | - | ||||||
| 79 | break; never executed: break; | 0 | ||||||
| 80 | default: never executed: default: | 0 | ||||||
| 81 | ret = "unknown"; | - | ||||||
| 82 | break; never executed: break; | 0 | ||||||
| 83 | } | - | ||||||
| 84 | - | |||||||
| 85 | return ret; never executed: return ret; | 0 | ||||||
| 86 | } | - | ||||||
| 87 | - | |||||||
| 88 | static void | - | ||||||
| 89 | apply_mode (FILE *stream, const char *mode) | - | ||||||
| 90 | { | - | ||||||
| 91 | char *buf = NULL; | - | ||||||
| 92 | int setvbuf_mode; | - | ||||||
| 93 | size_t size = 0; | - | ||||||
| 94 | - | |||||||
| 95 | if (*mode == '0')
| 4 | ||||||
| 96 | setvbuf_mode = _IONBF; executed 4 times by 1 test: setvbuf_mode = 2 ;Executed by:
| 4 | ||||||
| 97 | else if (*mode == 'L')
| 2 | ||||||
| 98 | setvbuf_mode = _IOLBF; /* FIXME: should we allow 1ML */ executed 2 times by 1 test: setvbuf_mode = 1 ;Executed by:
| 2 | ||||||
| 99 | else | - | ||||||
| 100 | { | - | ||||||
| 101 | setvbuf_mode = _IOFBF; | - | ||||||
| 102 | verify (SIZE_MAX <= ULONG_MAX); | - | ||||||
| 103 | size = strtoul (mode, NULL, 10); | - | ||||||
| 104 | if (size > 0)
| 0-2 | ||||||
| 105 | { | - | ||||||
| 106 | if (!(buf = malloc (size))) /* will be freed by fclose() */
| 0-2 | ||||||
| 107 | { | - | ||||||
| 108 | /* We could defer the allocation to libc, however since | - | ||||||
| 109 | glibc currently ignores the combination of NULL buffer | - | ||||||
| 110 | with non zero size, we'll fail here. */ | - | ||||||
| 111 | fprintf (stderr, | - | ||||||
| 112 | _("failed to allocate a %" PRIuMAX | - | ||||||
| 113 | " byte stdio buffer\n"), (uintmax_t) size); | - | ||||||
| 114 | return; never executed: return; | 0 | ||||||
| 115 | } | - | ||||||
| 116 | } executed 2 times by 1 test: end of blockExecuted by:
| 2 | ||||||
| 117 | else | - | ||||||
| 118 | { | - | ||||||
| 119 | fprintf (stderr, _("invalid buffering mode %s for %s\n"), | - | ||||||
| 120 | mode, fileno_to_name (fileno (stream))); | - | ||||||
| 121 | return; never executed: return; | 0 | ||||||
| 122 | } | - | ||||||
| 123 | } | - | ||||||
| 124 | - | |||||||
| 125 | if (setvbuf (stream, buf, setvbuf_mode, size) != 0)
| 0-8 | ||||||
| 126 | { | - | ||||||
| 127 | fprintf (stderr, _("could not set buffering of %s to mode %s\n"), | - | ||||||
| 128 | fileno_to_name (fileno (stream)), mode); | - | ||||||
| 129 | free (buf); | - | ||||||
| 130 | } never executed: end of block | 0 | ||||||
| 131 | } executed 8 times by 1 test: end of blockExecuted by:
| 8 | ||||||
| 132 | - | |||||||
| 133 | /* Use __attribute to avoid elision of __attribute__ on SUNPRO_C etc. */ | - | ||||||
| 134 | static void __attribute ((constructor)) | - | ||||||
| 135 | stdbuf (void) | - | ||||||
| 136 | { | - | ||||||
| 137 | char *e_mode = getenv ("_STDBUF_E"); | - | ||||||
| 138 | char *i_mode = getenv ("_STDBUF_I"); | - | ||||||
| 139 | char *o_mode = getenv ("_STDBUF_O"); | - | ||||||
| 140 | if (e_mode) /* Do first so can write errors to stderr */
| 1-5 | ||||||
| 141 | apply_mode (stderr, e_mode); executed 1 time by 1 test: apply_mode ( stderr , e_mode);Executed by:
| 1 | ||||||
| 142 | if (i_mode)
| 1-5 | ||||||
| 143 | apply_mode (stdin, i_mode); executed 1 time by 1 test: apply_mode ( stdin , i_mode);Executed by:
| 1 | ||||||
| 144 | if (o_mode)
| 0-6 | ||||||
| 145 | apply_mode (stdout, o_mode); executed 6 times by 1 test: apply_mode ( stdout , o_mode);Executed by:
| 6 | ||||||
| 146 | } executed 6 times by 1 test: end of blockExecuted by:
| 6 | ||||||
| Source code | Switch to Preprocessed file |