OpenCoverage

libstdbuf.c

Absolute File Name:/home/opencoverage/opencoverage/guest-scripts/coreutils/src/src/libstdbuf.c
Source codeSwitch to Preprocessed file
LineSourceCount
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-
64static const char *-
65fileno_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-
88static void-
89apply_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')
*mode == '0'Description
TRUEevaluated 4 times by 1 test
Evaluated by:
  • libstdbuf.so
FALSEevaluated 4 times by 1 test
Evaluated by:
  • libstdbuf.so
4
96 setvbuf_mode = _IONBF;
executed 4 times by 1 test: setvbuf_mode = 2 ;
Executed by:
  • libstdbuf.so
4
97 else if (*mode == 'L')
*mode == 'L'Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • libstdbuf.so
FALSEevaluated 2 times by 1 test
Evaluated by:
  • libstdbuf.so
2
98 setvbuf_mode = _IOLBF; /* FIXME: should we allow 1ML */
executed 2 times by 1 test: setvbuf_mode = 1 ;
Executed by:
  • libstdbuf.so
2
99 else-
100 {-
101 setvbuf_mode = _IOFBF;-
102 verify (SIZE_MAX <= ULONG_MAX);-
103 size = strtoul (mode, NULL, 10);-
104 if (size > 0)
size > 0Description
TRUEevaluated 2 times by 1 test
Evaluated by:
  • libstdbuf.so
FALSEnever evaluated
0-2
105 {-
106 if (!(buf = malloc (size))) /* will be freed by fclose() */
!(buf = malloc (size))Description
TRUEnever evaluated
FALSEevaluated 2 times by 1 test
Evaluated by:
  • libstdbuf.so
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 block
Executed by:
  • libstdbuf.so
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)
setvbuf (strea...de, size) != 0Description
TRUEnever evaluated
FALSEevaluated 8 times by 1 test
Evaluated by:
  • libstdbuf.so
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 block
Executed by:
  • libstdbuf.so
8
132-
133/* Use __attribute to avoid elision of __attribute__ on SUNPRO_C etc. */-
134static void __attribute ((constructor))-
135stdbuf (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 */
e_modeDescription
TRUEevaluated 1 time by 1 test
Evaluated by:
  • libstdbuf.so
FALSEevaluated 5 times by 1 test
Evaluated by:
  • libstdbuf.so
1-5
141 apply_mode (stderr, e_mode);
executed 1 time by 1 test: apply_mode ( stderr , e_mode);
Executed by:
  • libstdbuf.so
1
142 if (i_mode)
i_modeDescription
TRUEevaluated 1 time by 1 test
Evaluated by:
  • libstdbuf.so
FALSEevaluated 5 times by 1 test
Evaluated by:
  • libstdbuf.so
1-5
143 apply_mode (stdin, i_mode);
executed 1 time by 1 test: apply_mode ( stdin , i_mode);
Executed by:
  • libstdbuf.so
1
144 if (o_mode)
o_modeDescription
TRUEevaluated 6 times by 1 test
Evaluated by:
  • libstdbuf.so
FALSEnever evaluated
0-6
145 apply_mode (stdout, o_mode);
executed 6 times by 1 test: apply_mode ( stdout , o_mode);
Executed by:
  • libstdbuf.so
6
146}
executed 6 times by 1 test: end of block
Executed by:
  • libstdbuf.so
6
Source codeSwitch to Preprocessed file

Generated by Squish Coco 4.1.2