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 12907           static inline uint64_t checksum(b_header_block *block) {
15 12907           uint64_t sum = 0;
16             int i;
17              
18 6621291 100         for (i=0; i
19 6608384           sum += ((uint8_t *)(block))[i];
20             }
21              
22 12907           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 12907           static inline void encode_checksum(b_header_block *block) {
49 12907           memcpy( block->checksum, B_HEADER_EMPTY_CHECKSUM, B_HEADER_CHECKSUM_SIZE);
50 12907           snprintf(block->checksum, B_HEADER_CHECKSUM_LEN, B_HEADER_CHECKSUM_FORMAT, checksum(block));
51              
52 12907           block->checksum[7] = ' ';
53 12907           }
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 7069           b_header_block *b_header_encode_block(b_header_block *block, b_header *header) {
74 7069 50         if (header->suffix) {
75 7069           strncpy(block->suffix, header->suffix->str, 100);
76             }
77              
78 7069           snprintf(block->mode, B_HEADER_MODE_SIZE, B_HEADER_MODE_FORMAT, header->mode & S_IPERM);
79 7069           snprintf(block->uid, B_HEADER_UID_SIZE, B_HEADER_UID_FORMAT, header->uid);
80 7069           snprintf(block->gid, B_HEADER_GID_SIZE, B_HEADER_GID_FORMAT, header->gid);
81              
82 7069 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 7069           snprintf(block->size, B_HEADER_SIZE_SIZE, B_HEADER_LONG_SIZE_FORMAT, header->size);
86             }
87              
88 7069           snprintf(block->mtime, B_HEADER_MTIME_SIZE, B_HEADER_MTIME_FORMAT, header->mtime);
89              
90 7069           block->linktype = header->linktype;
91              
92 7069 100         if (header->linkdest != NULL) {
93 202           strncpy(block->linkdest, header->linkdest->str, B_HEADER_LINKDEST_SIZE);
94             }
95              
96 7069           memcpy(block->magic, B_HEADER_MAGIC, B_HEADER_MAGIC_SIZE);
97              
98 7069 50         if (header->user != NULL) {
99 7069           strncpy(block->user, header->user->str, B_HEADER_USER_SIZE);
100             }
101              
102 7069 50         if (header->group != NULL) {
103 7069           strncpy(block->group, header->group->str, B_HEADER_GROUP_SIZE);
104             }
105              
106 7069 100         if (header->major && header->minor) {
    50          
107 6981           snprintf(block->major, B_HEADER_MAJOR_SIZE, B_HEADER_MAJOR_FORMAT, header->major);
108 6981           snprintf(block->minor, B_HEADER_MINOR_SIZE, B_HEADER_MINOR_FORMAT, header->minor);
109             }
110              
111 7069 50         if (header->prefix) {
112 7069           strncpy(block->prefix, header->prefix->str, B_HEADER_PREFIX_SIZE);
113             }
114              
115 7069           encode_checksum(block);
116              
117 7069           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 7069           int b_header_set_usernames(b_header *header, b_string *user, b_string *group) {
152 7069           header->user = user;
153 7069           header->group = group;
154              
155 7069           return 0;
156             }
157              
158 7069           void b_header_destroy(b_header *header) {
159 7069 50         if (header == NULL) return;
160              
161 7069 50         if (header->prefix != NULL) {
162 7069           b_string_free(header->prefix);
163             }
164              
165 7069 50         if (header->suffix != NULL) {
166 7069           b_string_free(header->suffix);
167             }
168              
169 7069 100         if (header->linkdest != NULL) {
170 202           b_string_free(header->linkdest);
171             }
172              
173 7069 50         if (header->user != NULL) {
174 7069           b_string_free(header->user);
175             }
176              
177 7069 50         if (header->group != NULL) {
178 7069           b_string_free(header->group);
179             }
180              
181 7069           header->prefix = NULL;
182 7069           header->suffix = NULL;
183 7069           header->linkdest = NULL;
184 7069           header->user = NULL;
185 7069           header->group = NULL;
186              
187 7069           free(header);
188             }