File Coverage

src/b_buffer.c
Criterion Covered Total %
statement 83 119 69.7
branch 41 90 45.5
condition n/a
subroutine n/a
pod n/a
total 124 209 59.3


line stmt bran cond sub pod time code
1             #include
2             #include
3             #include
4             #include
5             #ifdef __linux__
6             #include
7             #include
8             #include
9             #endif
10             #include "b_buffer.h"
11              
12 92           b_buffer *b_buffer_new(size_t factor) {
13             b_buffer *buf;
14              
15 92 50         if ((buf = malloc(sizeof(*buf))) == NULL) {
16 0           goto error_malloc;
17             }
18              
19 92           buf->fd = 0;
20 92           buf->can_splice = 0;
21 92 50         buf->size = factor? factor * B_BUFFER_BLOCK_SIZE: B_BUFFER_DEFAULT_FACTOR * B_BUFFER_BLOCK_SIZE;
22 92           buf->unused = buf->size;
23              
24 92 50         if ((buf->data = malloc(buf->size)) == NULL) {
25 0           goto error_malloc_buf;
26             }
27              
28 92           memset(buf->data, 0x00, buf->size);
29              
30 92           return buf;
31              
32             error_malloc_buf:
33 0           buf->data = NULL;
34 0           buf->can_splice = 0;
35 0           buf->fd = 0;
36 0           buf->size = 0;
37              
38 0           free(buf);
39              
40             error_malloc:
41 0           return NULL;
42             }
43              
44 6629           int b_buffer_get_fd(b_buffer *buf) {
45 6629 50         if (buf == NULL) return 0;
46              
47 6629           return buf->fd;
48             }
49              
50 51           void b_buffer_set_fd(b_buffer *buf, int fd) {
51             #ifdef __linux__
52             struct stat st;
53             char *release, *kernel, *major, *minor;
54             int kernel_v, major_v, minor_v;
55             struct utsname unameData;
56             int uname_ok;
57             #endif
58 51 50         if (buf == NULL) return;
59              
60 51           buf->fd = fd;
61 51           buf->can_splice = 0;
62             #ifdef __linux__
63 51 50         if (fstat(fd, &st) == 0) {
64 51 100         if (S_ISFIFO(st.st_mode)) {
65 18           uname_ok = uname(&unameData);
66 18 50         if (uname_ok != -1) {
67 18           release = unameData.release;
68 18           kernel = strtok(release, ".");
69 18           major = strtok(NULL, ".");
70 18           minor = strtok(NULL, ".");
71 18 50         if (release && major && minor) {
    50          
    50          
72 18           kernel_v = strtol(kernel,NULL,10);
73 18           major_v = strtol(major,NULL,10);
74 18           minor_v = strtol(minor,NULL,10);
75 18 50         if (kernel_v >= 3 || (kernel_v == 2 && major_v == 6 && minor_v >= 31) ) {
    0          
    0          
    0          
76 18           buf->can_splice = 1;
77             }
78             }
79             }
80             }
81             }
82             #endif
83 51           return;
84             }
85              
86 0           size_t b_buffer_size(b_buffer *buf) {
87 0 0         if (buf == NULL) return 0;
88              
89 0           return buf->size;
90             }
91              
92 45323           size_t b_buffer_unused(b_buffer *buf) {
93 45323 50         if (buf == NULL) return 0;
94              
95 45323           return buf->unused;
96             }
97              
98 138410           int b_buffer_full(b_buffer *buf) {
99 138410 50         if (buf == NULL) return 0;
100              
101 138410           return buf->unused == 0;
102             }
103              
104 92299           static inline size_t padded_size(size_t size) {
105 92299 100         if (size % B_BUFFER_BLOCK_SIZE == 0) {
106 86024           return size;
107             }
108              
109 6275           return size + (B_BUFFER_BLOCK_SIZE - (size % B_BUFFER_BLOCK_SIZE));
110             }
111              
112 6275           off_t b_buffer_reclaim(b_buffer *buf, size_t used, size_t given) {
113 6275           size_t padded_len = padded_size(used);
114             off_t amount;
115              
116 6275 50         if (buf == NULL || given == 0 || given % B_BUFFER_BLOCK_SIZE) {
    50          
    50          
117 0           errno = EINVAL;
118 0           return -1;
119             }
120              
121 6275           amount = given - padded_len;
122              
123 6275           buf->unused += amount;
124              
125 6275           return amount;
126             }
127              
128 86024           void *b_buffer_get_block(b_buffer *buf, size_t len, off_t *given) {
129             size_t offset;
130 86024           size_t padded_len = padded_size(len);
131              
132 86024 50         if (buf == NULL) {
133 0           errno = EINVAL;
134 0           goto error;
135             }
136              
137 86024 50         if (len == 0) return NULL;
138              
139 86024 50         if (buf->fd == 0) {
140 0           errno = EBADF;
141 0           goto error;
142             }
143              
144             /*
145             * If the buffer is full prior to allocating a block, then flush the buffer
146             * to make room for a new block.
147             */
148 86024 100         if (b_buffer_full(buf)) {
149 1645 50         if (b_buffer_flush(buf) < 0) {
150 0           goto error;
151             }
152             }
153              
154             /*
155             * Complain if the buffer block request calls for more buffer space than is
156             * available.
157             */
158 86024 50         if (padded_len > buf->unused) {
159 0           errno = EFBIG;
160 0           goto error;
161             }
162              
163             /*
164             * Determine the physical location of the buffer block to return to the
165             * caller.
166             */
167 86024           offset = buf->size - buf->unused;
168              
169             /*
170             * Update the buffer to indicate that less fill data is unused.
171             */
172 86024           buf->unused -= padded_len;
173              
174             /*
175             * Update the 'given' parameter to indicate how much data was given.
176             */
177 86024 50         if (given) {
178 86024           *given = padded_len;
179             }
180              
181 86024           return buf->data + offset;
182              
183             error:
184 0 0         if (given) {
185 0           *given = -1;
186             }
187              
188 0           return NULL;
189             }
190              
191 41409           ssize_t b_buffer_flush(b_buffer *buf) {
192 41409           ssize_t ret = 0;
193 41409           ssize_t off = 0;
194              
195 41409 50         if (buf == NULL || buf->data == NULL) {
    50          
196 0           errno = EINVAL;
197 0           return -1;
198             }
199              
200 41409 50         if (buf->fd == 0) {
201 0           errno = EBADF;
202 0           return -1;
203             }
204              
205 41409 50         if (buf->size == 0) return 0;
206 41409 100         if (buf->unused == buf->size) return 0;
207              
208 82806 100         while ((off < buf->size) || (ret < 0 && errno == EINTR)) {
    50          
    0          
209 41403 50         if ((ret = write(buf->fd, buf->data + off, buf->size - off)) < 0) {
210 0 0         if (errno != EINTR)
211 0           return ret;
212             }
213 41403 50         else if (!ret) {
214 0           break;
215             }
216             else {
217 41403           off += ret;
218             }
219             }
220              
221 41403           memset(buf->data, 0x00, buf->size);
222              
223 41403           buf->unused = buf->size;
224              
225 41403           return ret;
226             }
227              
228 0           void b_buffer_reset(b_buffer *buf) {
229 0 0         if (buf == NULL) return;
230              
231 0           buf->fd = 0;
232 0           buf->unused = buf->size;
233              
234 0 0         if (buf->data == NULL) return;
235              
236 0           memset(buf->data, 0x00, buf->size);
237             }
238              
239 92           void b_buffer_destroy(b_buffer *buf) {
240 92 50         if (buf == NULL) return;
241              
242 92 50         if (buf->data) {
243 92           free(buf->data);
244 92           buf->data = NULL;
245             }
246              
247 92           buf->fd = 0;
248 92           buf->size = 0;
249 92           buf->unused = 0;
250              
251 92           free(buf);
252             }