File Coverage

src/b_file.c
Criterion Covered Total %
statement 69 80 86.2
branch 42 60 70.0
condition n/a
subroutine n/a
pod n/a
total 111 140 79.2


line stmt bran cond sub pod time code
1             #ifdef __linux__
2             #define _GNU_SOURCE /* See feature_test_macros(7) */
3             #endif
4             #include
5             #include
6             #include
7             #include
8             #include
9             #include
10             #include
11             #include
12             #include
13             #include
14              
15             #include "b_builder.h"
16             #include "b_header.h"
17             #include "b_string.h"
18             #include "b_buffer.h"
19             #include "b_file.h"
20              
21             #define MAX_CHUNK_SIZE (16 * 1024 * 1024)
22              
23             /*
24             * Meant to be used in conjunction with header.c/b_header_encode_longlink_block(),
25             * this method will write out as many 512-byte blocks as necessary to contain the
26             * full path.
27             */
28 5834           off_t b_file_write_path_blocks(b_buffer *buf, b_string *path) {
29             size_t i, len;
30 5834           off_t blocklen = 0;
31 5834           off_t total = 0;
32              
33 5834           len = b_string_len(path);
34              
35 33628 100         for (i=0; i
36 27794           size_t left = len - i;
37 27794           size_t copylen = left < B_BLOCK_SIZE? left: B_BLOCK_SIZE;
38              
39             unsigned char *block;
40              
41 27794 50         if ((block = b_buffer_get_block(buf, B_BLOCK_SIZE, &blocklen)) == NULL) {
42 0           goto error_io;
43             }
44              
45 27794           memcpy(block, path->str + i, copylen);
46              
47 27794           total += blocklen;
48             }
49              
50 5834           return total;
51              
52             error_io:
53 5834           return -1;
54             }
55              
56 4           off_t b_file_write_pax_path_blocks(b_buffer *buf, b_string *path, b_string *linkdest) {
57 4           size_t i, len, full_len, link_full_len = 0, buflen, total_len;
58 4           off_t blocklen = 0;
59 4           off_t total = 0;
60 4           char *buffer = NULL;
61              
62 4           len = b_string_len(path);
63              
64 4           full_len = b_header_compute_pax_length(path, "path");
65              
66 4 50         if (linkdest)
67 0           link_full_len = b_header_compute_pax_length(linkdest, "linkpath");
68              
69 4           total_len = full_len + link_full_len;
70              
71             /* In case we have a broken snprintf. */
72 4 50         if (full_len == (size_t)-1)
73 0           goto error_io;
74              
75 4 50         if ((buffer = malloc(total_len + 1)) == NULL)
76 0           goto error_mem;
77              
78 4           snprintf(buffer, total_len + 1, "%d path=%s\n", full_len, path->str);
79 4 50         if (linkdest)
80 0           snprintf(buffer + full_len, link_full_len + 1, "%d linkpath=%s\n", link_full_len, linkdest->str);
81              
82 8 100         for (i=0; i
83 4           size_t left = total_len - i;
84 4           size_t copylen = left < B_BLOCK_SIZE? left: B_BLOCK_SIZE;
85              
86             unsigned char *block;
87              
88              
89 4 50         if ((block = b_buffer_get_block(buf, B_BLOCK_SIZE, &blocklen)) == NULL) {
90 0           goto error_io;
91             }
92              
93 4           memcpy(block, buffer + i, copylen);
94 4           total += blocklen;
95             }
96              
97 4           free(buffer);
98 4           return total;
99              
100             error_io:
101             error_mem:
102 0           free(buffer);
103 4           return -1;
104             }
105              
106 6775           off_t b_file_write_contents(b_buffer *buf, int file_fd, off_t file_size) {
107 6775           ssize_t rlen = 0;
108 6775           off_t blocklen = 0, total = 0, real_total = 0, max_read = 0;
109             #ifdef __linux__
110 6775           int emptied_buffer = 0, splice_total = 0;
111             #endif
112              
113             do {
114 52386 100         if (b_buffer_full(buf)) {
115 39737 50         if (b_buffer_flush(buf) < 0) {
116 0           goto error_io;
117             }
118             #ifdef __linux__
119 39737           emptied_buffer = 1;
120             #endif
121             }
122              
123 52386           max_read = file_size - real_total;
124              
125 52386 100         if (max_read > MAX_CHUNK_SIZE) {
126 32512           max_read = MAX_CHUNK_SIZE;
127             }
128 19874 100         else if (max_read == 0) {
129 6771           break;
130             }
131             #ifdef __linux__
132             /*
133             * Once we have cleared out the buffer we can read the rest of the file
134             * with splice and write out a tar padding.
135             */
136 45615 100         if (emptied_buffer && buf->can_splice) {
    100          
137 292 50         if ((rlen = splice(file_fd, NULL, buf->fd, NULL, max_read, 0))){
138 292 50         if (rlen < 0) {
139 0           buf->can_splice = 0;
140             }
141             else {
142 292           splice_total += rlen;
143 292           total += rlen;
144             }
145             }
146             }
147 45615 100         if (!emptied_buffer || !buf->can_splice) {
    100          
148             #endif
149             unsigned char *block;
150              
151 45323 50         if ((block = b_buffer_get_block(buf, b_buffer_unused(buf), &blocklen)) == NULL) {
152 0           goto error_io;
153             }
154              
155 45323 100         if (max_read > blocklen) {
156 39048           max_read = blocklen;
157             }
158              
159             read_retry:
160 45323 100         if ((rlen = read(file_fd, block, max_read)) < max_read) {
161 4 50         if (rlen < 0 && errno == EINTR) { goto read_retry; }
    0          
162              
163 4           goto error_io;
164             }
165              
166 45319           total += blocklen;
167             /*
168             * Reclaim any amount of bytes from the buffer that weren't used to
169             * store the chunk read() from the filesystem.
170             */
171 45319 100         if (blocklen - rlen) {
172 6275           total -= b_buffer_reclaim(buf, rlen, blocklen);
173             }
174             #ifdef __linux__
175             }
176             #endif
177 45611           real_total += rlen;
178 45611 50         } while (rlen > 0);
179              
180             #ifdef __linux__
181 6771 100         if (splice_total && buf->can_splice && total % B_BUFFER_BLOCK_SIZE != 0) {
    50          
    50          
182             /*
183             * finished splice, now complete the block by writing out zeros to make
184             * tar happy
185             */
186 292 50         if ((write(buf->fd, buf->data, B_BUFFER_BLOCK_SIZE - (total % B_BUFFER_BLOCK_SIZE))) < 0) {
187 0           goto error_io;
188             }
189             }
190             #endif
191              
192 6771           return total;
193              
194             error_io:
195 4 50         if (!errno) {
196 4           errno = EINVAL;
197             }
198 6775           return -1;
199             }