File Coverage

src/b_header.c
Criterion Covered Total %
statement 78 91 85.7
branch 22 38 57.8
condition n/a
subroutine n/a
pod n/a
total 100 129 77.5


line stmt bran cond sub pod time code
1             #include
2             #include
3             #include
4             #include
5             #include
6             #include
7             #include
8             #include
9             #include "b_header.h"
10             #include "b_stack.h"
11             #include "b_path.h"
12             #include "b_util.h"
13              
14 12508           static inline uint64_t checksum(b_header_block *block) {
15 12508           uint64_t sum = 0;
16             int i;
17              
18 6416604 100         for (i=0; i
19 6404096           sum += ((uint8_t *)(block))[i];
20             }
21              
22 12508           return sum;
23             }
24              
25 0           static inline int is_big_endian() {
26 0           uint16_t num = 1;
27              
28 0           return ((uint8_t *)&num)[1];
29             }
30              
31 0           static inline void encode_base256_value(unsigned char *field, size_t len, uint64_t value) {
32             size_t i;
33 0           size_t value_size = sizeof(value);
34 0           size_t offset = len - value_size;
35              
36 0 0         for (i=0; i
37 0 0         int from_i = is_big_endian()? i: value_size - i - 1;
38              
39 0           field[offset + i] = ((uint8_t *)&value)[from_i];
40             }
41              
42             /*
43             * Set the uppermost bit to indicate a base256-encoded size value.
44             */
45 0           field[0] |= 0x80;
46 0           }
47              
48 12508           static inline void encode_checksum(b_header_block *block) {
49 12508           memcpy( block->checksum, B_HEADER_EMPTY_CHECKSUM, B_HEADER_CHECKSUM_SIZE);
50 12508           snprintf(block->checksum, B_HEADER_CHECKSUM_LEN, B_HEADER_CHECKSUM_FORMAT, checksum(block));
51              
52 12508           block->checksum[7] = ' ';
53 12508           }
54              
55 8           size_t b_header_compute_pax_length(b_string *path, const char *record) {
56             size_t len, i;
57             char shortbuf[32];
58              
59 8           len = b_string_len(path);
60              
61             /* snprintf returns the number of characters (excluding the NUL) we would
62             * have written had space been available. Iterate three times to be sure
63             * the value is stable.
64             */
65 32 100         for (i=0; i<3; i++) {
66 24           len = snprintf(shortbuf, sizeof(shortbuf), "%d %s=%s\n", len, record, path->str);
67             }
68              
69 8           return len;
70             }
71              
72              
73 6670           b_header_block *b_header_encode_block(b_header_block *block, b_header *header) {
74 6670 50         if (header->suffix) {
75 6670           strncpy(block->suffix, header->suffix->str, 100);
76             }
77              
78 6670           snprintf(block->mode, B_HEADER_MODE_SIZE, B_HEADER_MODE_FORMAT, header->mode & S_IPERM);
79 6670           snprintf(block->uid, B_HEADER_UID_SIZE, B_HEADER_UID_FORMAT, header->uid);
80 6670           snprintf(block->gid, B_HEADER_GID_SIZE, B_HEADER_GID_FORMAT, header->gid);
81              
82 6670 50         if (header->size >= B_HEADER_MAX_FILE_SIZE) {
83 0           encode_base256_value(block->size, B_HEADER_SIZE_SIZE, header->size);
84             } else {
85 6670           snprintf(block->size, B_HEADER_SIZE_SIZE, B_HEADER_LONG_SIZE_FORMAT, header->size);
86             }
87              
88 6670           snprintf(block->mtime, B_HEADER_MTIME_SIZE, B_HEADER_MTIME_FORMAT, header->mtime);
89              
90 6670           block->linktype = header->linktype;
91              
92 6670 100         if (header->linkdest != NULL) {
93 3           strncpy(block->linkdest, header->linkdest->str, B_HEADER_LINKDEST_SIZE);
94             }
95              
96 6670           memcpy(block->magic, B_HEADER_MAGIC, B_HEADER_MAGIC_SIZE);
97              
98 6670 50         if (header->user != NULL) {
99 6670           strncpy(block->user, header->user->str, B_HEADER_USER_SIZE);
100             }
101              
102 6670 50         if (header->group != NULL) {
103 6670           strncpy(block->group, header->group->str, B_HEADER_GROUP_SIZE);
104             }
105              
106 6670 100         if (header->major && header->minor) {
    50          
107 6583           snprintf(block->major, B_HEADER_MAJOR_SIZE, B_HEADER_MAJOR_FORMAT, header->major);
108 6583           snprintf(block->minor, B_HEADER_MINOR_SIZE, B_HEADER_MINOR_FORMAT, header->minor);
109             }
110              
111 6670 50         if (header->prefix) {
112 6670           strncpy(block->prefix, header->prefix->str, B_HEADER_PREFIX_SIZE);
113             }
114              
115 6670           encode_checksum(block);
116              
117 6670           return block;
118             }
119              
120 5834           b_header_block *b_header_encode_longlink_block(b_header_block *block, b_string *path, int type) {
121 5834           memcpy( block->magic, B_HEADER_MAGIC, B_HEADER_MAGIC_SIZE);
122 5834           snprintf(block->suffix, B_HEADER_SUFFIX_SIZE, B_HEADER_LONGLINK_PATH);
123 5834           snprintf(block->size, B_HEADER_SIZE_SIZE, B_HEADER_INT_SIZE_FORMAT, b_string_len(path));
124              
125 5834           block->linktype = type;
126              
127 5834           encode_checksum(block);
128              
129 5834           return block;
130             }
131              
132 4           b_header_block *b_header_encode_pax_block(b_header_block *block, b_header *header, b_string *path) {
133 4           size_t pax_len = b_header_compute_pax_length(path, "path");
134              
135 4 50         if (header->linkdest)
136 0           pax_len += b_header_compute_pax_length(header->linkdest, "linkpath");
137              
138 4           b_header_encode_block(block, header);
139              
140 4           snprintf(block->size, B_HEADER_SIZE_SIZE, B_HEADER_LONG_SIZE_FORMAT, (unsigned long long)pax_len);
141              
142 4           memset(block->prefix, 0, sizeof(block->prefix));
143 4           snprintf(block->prefix, sizeof(block->prefix), "./PaxHeaders.%d", getpid());
144 4           block->linktype = B_HEADER_PAX_TYPE;
145              
146 4           encode_checksum(block);
147              
148 4           return block;
149             }
150              
151 6670           int b_header_set_usernames(b_header *header, b_string *user, b_string *group) {
152 6670           header->user = user;
153 6670           header->group = group;
154              
155 6670           return 0;
156             }
157              
158 6670           void b_header_destroy(b_header *header) {
159 6670 50         if (header == NULL) return;
160              
161 6670 50         if (header->prefix != NULL) {
162 6670           b_string_free(header->prefix);
163             }
164              
165 6670 50         if (header->suffix != NULL) {
166 6670           b_string_free(header->suffix);
167             }
168              
169 6670 100         if (header->linkdest != NULL) {
170 3           b_string_free(header->linkdest);
171             }
172              
173 6670 50         if (header->user != NULL) {
174 6670           b_string_free(header->user);
175             }
176              
177 6670 50         if (header->group != NULL) {
178 6670           b_string_free(header->group);
179             }
180              
181 6670           header->prefix = NULL;
182 6670           header->suffix = NULL;
183 6670           header->linkdest = NULL;
184 6670           header->user = NULL;
185 6670           header->group = NULL;
186              
187 6670           free(header);
188             }