clang -cc1 -cc1 -triple x86_64-pc-linux-gnu -analyze -disable-free -clear-ast-before-backend -disable-llvm-verifier -discard-value-names -main-file-name mar_read.c -analyzer-checker=core -analyzer-checker=apiModeling -analyzer-checker=unix -analyzer-checker=deadcode -analyzer-checker=security.insecureAPI.UncheckedReturn -analyzer-checker=security.insecureAPI.getpw -analyzer-checker=security.insecureAPI.gets -analyzer-checker=security.insecureAPI.mktemp -analyzer-checker=security.insecureAPI.mkstemp -analyzer-checker=security.insecureAPI.vfork -analyzer-checker=nullability.NullPassedToNonnull -analyzer-checker=nullability.NullReturnedFromNonnull -analyzer-output plist -w -setup-static-analyzer -analyzer-config-compatibility-mode=true -mrelocation-model pic -pic-level 2 -pic-is-pie -mframe-pointer=none -fmath-errno -ffp-contract=on -fno-rounding-math -mconstructor-aliases -funwind-tables=2 -target-cpu x86-64 -tune-cpu generic -debugger-tuning=gdb -fdebug-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/modules/libmar/src -fcoverage-compilation-dir=/var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/modules/libmar/src -resource-dir /usr/lib/llvm-19/lib/clang/19 -D XP_UNIX -D DEBUG=1 -I /var/lib/jenkins/workspace/firefox-scan-build/modules/libmar/src -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/modules/libmar/src -I /var/lib/jenkins/workspace/firefox-scan-build/other-licenses/nsis/Contrib/CityHash/cityhash -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include -I /var/lib/jenkins/workspace/firefox-scan-build/obj-x86_64-pc-linux-gnu/dist/include/nspr -internal-isystem /usr/lib/llvm-19/lib/clang/19/include -internal-isystem /usr/local/include -internal-isystem /usr/lib/gcc/x86_64-linux-gnu/14/../../../../x86_64-linux-gnu/include -internal-externc-isystem /usr/include/x86_64-linux-gnu -internal-externc-isystem /include -internal-externc-isystem /usr/include -O3 -std=gnu11 -ferror-limit 19 -fgnuc-version=4.2.1 -fskip-odr-check-in-gmf -vectorize-loops -vectorize-slp -analyzer-checker optin.performance.Padding -analyzer-output=html -analyzer-config stable-report-filename=true -faddrsig -D__GCC_HAVE_DWARF2_CFI_ASM=1 -o /tmp/scan-build-2024-09-22-115206-3586786-1 -x c /var/lib/jenkins/workspace/firefox-scan-build/modules/libmar/src/mar_read.c
1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | #include <sys/types.h> |
8 | #include <fcntl.h> |
9 | #include <stdlib.h> |
10 | #include <string.h> |
11 | #include "city.h" |
12 | #include "mar_private.h" |
13 | #include "mar.h" |
14 | #ifdef XP_WIN |
15 | # define strdup _strdup |
16 | #endif |
17 | |
18 | |
19 | |
20 | |
21 | |
22 | |
23 | #define MAXADDITIONALBLOCKSIZE 96 |
24 | |
25 | static uint32_t mar_hash_name(const char* name) { |
26 | return CityHash64(name, strlen(name)) % TABLESIZE; |
27 | } |
28 | |
29 | static int mar_insert_item(MarFile* mar, const char* name, uint32_t namelen, |
30 | uint32_t offset, uint32_t length, uint32_t flags) { |
31 | MarItem *item, *root; |
32 | uint32_t hash; |
33 | |
34 | item = (MarItem*)malloc(sizeof(MarItem) + namelen); |
35 | if (!item) { |
36 | return -1; |
37 | } |
38 | item->next = NULL; |
39 | item->offset = offset; |
40 | item->length = length; |
41 | item->flags = flags; |
42 | memcpy(item->name, name, namelen + 1); |
43 | |
44 | hash = mar_hash_name(name); |
45 | |
46 | root = mar->item_table[hash]; |
47 | if (!root) { |
48 | mar->item_table[hash] = item; |
49 | } else { |
50 | |
51 | while (root->next) root = root->next; |
52 | root->next = item; |
53 | } |
54 | return 0; |
55 | } |
56 | |
57 | static int mar_consume_index(MarFile* mar, char** buf, const char* buf_end) { |
58 | |
59 | |
60 | |
61 | |
62 | |
63 | |
64 | |
65 | |
66 | uint32_t offset; |
67 | uint32_t length; |
68 | uint32_t flags; |
69 | const char* name; |
70 | int namelen; |
71 | |
72 | if ((buf_end - *buf) < (int)(3 * sizeof(uint32_t) + 2)) { |
73 | return -1; |
74 | } |
75 | |
76 | memcpy(&offset, *buf, sizeof(offset)); |
77 | *buf += sizeof(offset); |
78 | |
79 | memcpy(&length, *buf, sizeof(length)); |
80 | *buf += sizeof(length); |
81 | |
82 | memcpy(&flags, *buf, sizeof(flags)); |
83 | *buf += sizeof(flags); |
84 | |
85 | offset = ntohl(offset); |
86 | length = ntohl(length); |
87 | flags = ntohl(flags); |
88 | |
89 | name = *buf; |
90 | |
91 | while (**buf) { |
92 | |
93 | if (*buf == (buf_end - 1)) { |
94 | return -1; |
95 | } |
96 | ++(*buf); |
97 | } |
98 | namelen = (*buf - name); |
99 | |
100 | if (namelen < 0) { |
101 | return -1; |
102 | } |
103 | |
104 | if (*buf == buf_end) { |
105 | return -1; |
106 | } |
107 | ++(*buf); |
108 | |
109 | return mar_insert_item(mar, name, namelen, offset, length, flags); |
110 | } |
111 | |
112 | static int mar_read_index(MarFile* mar) { |
113 | char id[MAR_ID_SIZE], *buf, *bufptr, *bufend; |
114 | uint32_t offset_to_index, size_of_index; |
115 | size_t mar_position = 0; |
116 | |
117 | |
118 | if (mar_read_buffer(mar, id, &mar_position, MAR_ID_SIZE) != 0) { |
119 | return -1; |
120 | } |
121 | if (memcmp(id, MAR_ID, MAR_ID_SIZE) != 0) { |
122 | return -1; |
123 | } |
124 | |
125 | if (mar_read_buffer(mar, &offset_to_index, &mar_position, sizeof(uint32_t)) != |
126 | 0) { |
127 | return -1; |
128 | } |
129 | offset_to_index = ntohl(offset_to_index); |
130 | |
131 | mar_position = 0; |
132 | if (mar_buffer_seek(mar, &mar_position, offset_to_index) != 0) { |
133 | return -1; |
134 | } |
135 | if (mar_read_buffer(mar, &size_of_index, &mar_position, sizeof(uint32_t)) != |
136 | 0) { |
137 | return -1; |
138 | } |
139 | size_of_index = ntohl(size_of_index); |
140 | |
141 | buf = (char*)malloc(size_of_index); |
142 | if (!buf) { |
143 | return -1; |
144 | } |
145 | if (mar_read_buffer(mar, buf, &mar_position, size_of_index) != 0) { |
146 | free(buf); |
147 | return -1; |
148 | } |
149 | |
150 | bufptr = buf; |
151 | bufend = buf + size_of_index; |
152 | while (bufptr < bufend && mar_consume_index(mar, &bufptr, bufend) == 0); |
153 | |
154 | free(buf); |
155 | return (bufptr == bufend) ? 0 : -1; |
156 | } |
157 | |
158 | |
159 | |
160 | |
161 | |
162 | |
163 | |
164 | |
165 | |
166 | static int mar_insert_offset(MarFile* mar, uint32_t offset, uint32_t length) { |
167 | |
168 | if (length == 0) { |
169 | return 1; |
170 | } |
171 | |
172 | SeenIndex* index = (SeenIndex*)malloc(sizeof(SeenIndex)); |
173 | if (!index) { |
174 | return -1; |
175 | } |
176 | index->next = NULL; |
177 | index->offset = offset; |
178 | index->length = length; |
179 | uint32_t index_end = index->offset + index->length - 1; |
180 | |
181 | |
182 | if (mar->index_list == NULL) { |
183 | mar->index_list = index; |
184 | return 1; |
185 | } |
186 | |
187 | |
188 | SeenIndex* previous; |
189 | SeenIndex* current = mar->index_list; |
190 | while (current != NULL) { |
191 | uint32_t current_end = current->offset + current->length - 1; |
192 | |
193 | |
194 | |
195 | if ((index->offset >= current->offset && index->offset <= current_end) || |
196 | (index_end >= current->offset && index_end <= current_end) || |
197 | (current->offset >= index->offset && current->offset <= index_end) || |
198 | (current_end >= index->offset && current_end <= index_end)) { |
199 | free(index); |
200 | return 0; |
201 | } |
202 | |
203 | |
204 | previous = current; |
205 | current = current->next; |
206 | } |
207 | |
208 | |
209 | previous->next = index; |
210 | return 1; |
211 | } |
212 | |
213 | |
214 | |
215 | |
216 | |
217 | |
218 | static MarReadResult mar_fpopen(FILE* fp, MarFile** out_mar) { |
219 | *out_mar = NULL; |
220 | MarFile* mar; |
221 | |
222 | mar = (MarFile*)malloc(sizeof(*mar)); |
223 | if (!mar) { |
| 4 | | Assuming 'mar' is non-null | |
|
| |
224 | return MAR_MEM_ERROR; |
225 | } |
226 | |
227 | off_t buffer_size = -1; |
228 | if (fseeko(fp, 0, SEEK_END) == 0) { |
| |
229 | buffer_size = ftello(fp); |
230 | } |
231 | rewind(fp); |
| 7 | | After calling 'rewind' reading 'errno' is required to find out if the call has failed | |
|
232 | if (buffer_size < 0) { |
| |
233 | fprintf(stderr, "Warning: MAR size could not be determined\n"); |
234 | buffer_size = MAX_SIZE_OF_MAR_FILE; |
235 | } |
236 | if (buffer_size > MAX_SIZE_OF_MAR_FILE) { |
| 9 | | Assuming 'buffer_size' is <= MAX_SIZE_OF_MAR_FILE | |
|
| |
237 | fprintf(stderr, "ERROR: MAR exceeds maximum size (%lli)\n", |
238 | (long long int)buffer_size); |
239 | free(mar); |
240 | return MAR_FILE_TOO_BIG_ERROR; |
241 | } |
242 | |
243 | mar->buffer = malloc(buffer_size); |
| 11 | | Value of 'errno' was not checked and may be overwritten by function 'malloc' |
|
244 | if (!mar->buffer) { |
245 | fprintf(stderr, "ERROR: MAR buffer could not be allocated\n"); |
246 | free(mar); |
247 | return MAR_MEM_ERROR; |
248 | } |
249 | mar->data_len = fread(mar->buffer, 1, buffer_size, fp); |
250 | if (fgetc(fp) != EOF) { |
251 | fprintf(stderr, "ERROR: File is larger than buffer (%lli)\n", |
252 | (long long int)buffer_size); |
253 | free(mar->buffer); |
254 | free(mar); |
255 | return MAR_IO_ERROR; |
256 | } |
257 | if (ferror(fp)) { |
258 | fprintf(stderr, "ERROR: Failed to read MAR\n"); |
259 | free(mar->buffer); |
260 | free(mar); |
261 | return MAR_IO_ERROR; |
262 | } |
263 | |
264 | mar->item_table_is_valid = 0; |
265 | memset(mar->item_table, 0, sizeof(mar->item_table)); |
266 | mar->index_list = NULL; |
267 | |
268 | *out_mar = mar; |
269 | return MAR_READ_SUCCESS; |
270 | } |
271 | |
272 | MarReadResult mar_open(const char* path, MarFile** out_mar) { |
273 | *out_mar = NULL; |
274 | |
275 | FILE* fp; |
276 | |
277 | fp = fopen(path, "rb"); |
278 | if (!fp) { |
| |
279 | fprintf(stderr, "ERROR: could not open file in mar_open()\n"); |
280 | perror(path); |
281 | return MAR_IO_ERROR; |
282 | } |
283 | |
284 | MarReadResult result = mar_fpopen(fp, out_mar); |
| |
285 | fclose(fp); |
286 | return result; |
287 | } |
288 | |
289 | #ifdef XP_WIN |
290 | MarReadResult mar_wopen(const wchar_t* path, MarFile** out_mar) { |
291 | *out_mar = NULL; |
292 | |
293 | FILE* fp; |
294 | |
295 | _wfopen_s(&fp, path, L"rb"); |
296 | if (!fp) { |
297 | fprintf(stderr, "ERROR: could not open file in mar_wopen()\n"); |
298 | _wperror(path); |
299 | return MAR_IO_ERROR; |
300 | } |
301 | |
302 | MarReadResult result = mar_fpopen(fp, out_mar); |
303 | fclose(fp); |
304 | return result; |
305 | } |
306 | #endif |
307 | |
308 | void mar_close(MarFile* mar) { |
309 | MarItem* item; |
310 | SeenIndex* index; |
311 | int i; |
312 | |
313 | free(mar->buffer); |
314 | |
315 | for (i = 0; i < TABLESIZE; ++i) { |
316 | item = mar->item_table[i]; |
317 | while (item) { |
318 | MarItem* temp = item; |
319 | item = item->next; |
320 | free(temp); |
321 | } |
322 | } |
323 | |
324 | while (mar->index_list != NULL) { |
325 | index = mar->index_list; |
326 | mar->index_list = index->next; |
327 | free(index); |
328 | } |
329 | |
330 | free(mar); |
331 | } |
332 | |
333 | int mar_read_buffer(MarFile* mar, void* dest, size_t* position, size_t size) { |
334 | |
335 | |
336 | |
337 | if (size > mar->data_len) { |
338 | return -1; |
339 | } |
340 | if (*position > mar->data_len - size) { |
341 | return -1; |
342 | } |
343 | memcpy(dest, mar->buffer + *position, size); |
344 | *position += size; |
345 | return 0; |
346 | } |
347 | |
348 | int mar_read_buffer_max(MarFile* mar, void* dest, size_t* position, |
349 | size_t size) { |
350 | |
351 | |
352 | |
353 | if (mar->data_len <= *position) { |
354 | return 0; |
355 | } |
356 | size_t read_count = mar->data_len - *position; |
357 | if (read_count > size) { |
358 | read_count = size; |
359 | } |
360 | memcpy(dest, mar->buffer + *position, read_count); |
361 | *position += read_count; |
362 | return read_count; |
363 | } |
364 | |
365 | int mar_buffer_seek(MarFile* mar, size_t* position, size_t distance) { |
366 | |
367 | |
368 | |
369 | if (distance > mar->data_len) { |
370 | return -1; |
371 | } |
372 | if (*position > mar->data_len - distance) { |
373 | return -1; |
374 | } |
375 | *position += distance; |
376 | return 0; |
377 | } |
378 | |
379 | |
380 | |
381 | |
382 | |
383 | |
384 | |
385 | |
386 | |
387 | |
388 | |
389 | |
390 | |
391 | |
392 | |
393 | |
394 | |
395 | |
396 | |
397 | |
398 | |
399 | |
400 | |
401 | |
402 | int get_open_mar_file_info(MarFile* mar, size_t* mar_position, |
403 | int* hasSignatureBlock, uint32_t* numSignatures, |
404 | int* hasAdditionalBlocks, |
405 | uint32_t* offsetAdditionalBlocks, |
406 | uint32_t* numAdditionalBlocks) { |
407 | uint32_t offsetToIndex, offsetToContent, signatureCount, signatureLen, i; |
408 | |
409 | |
410 | if (!hasSignatureBlock && !hasAdditionalBlocks) { |
411 | return -1; |
412 | } |
413 | |
414 | |
415 | *mar_position = 0; |
416 | if (mar_buffer_seek(mar, mar_position, MAR_ID_SIZE) != 0) { |
417 | return -1; |
418 | } |
419 | |
420 | |
421 | if (mar_read_buffer(mar, &offsetToIndex, mar_position, |
422 | sizeof(offsetToIndex)) != 0) { |
423 | return -1; |
424 | } |
425 | offsetToIndex = ntohl(offsetToIndex); |
426 | |
427 | if (numSignatures) { |
428 | |
429 | if (mar_buffer_seek(mar, mar_position, sizeof(uint64_t)) != 0) { |
430 | return -1; |
431 | } |
432 | |
433 | |
434 | if (mar_read_buffer(mar, numSignatures, mar_position, |
435 | sizeof(*numSignatures)) != 0) { |
436 | return -1; |
437 | } |
438 | *numSignatures = ntohl(*numSignatures); |
439 | } |
440 | |
441 | |
442 | |
443 | |
444 | *mar_position = 0; |
445 | if (mar_buffer_seek(mar, mar_position, offsetToIndex) != 0) { |
446 | return -1; |
447 | } |
448 | |
449 | if (mar_buffer_seek(mar, mar_position, sizeof(uint32_t)) != 0) { |
450 | return -1; |
451 | } |
452 | |
453 | |
454 | if (mar_read_buffer(mar, &offsetToContent, mar_position, |
455 | sizeof(offsetToContent)) != 0) { |
456 | return -1; |
457 | } |
458 | offsetToContent = ntohl(offsetToContent); |
459 | |
460 | |
461 | if (hasSignatureBlock) { |
462 | if (offsetToContent == MAR_ID_SIZE + sizeof(uint32_t)) { |
463 | *hasSignatureBlock = 0; |
464 | } else { |
465 | *hasSignatureBlock = 1; |
466 | } |
467 | } |
468 | |
469 | |
470 | |
471 | if (!hasAdditionalBlocks) { |
472 | return 0; |
473 | } |
474 | |
475 | |
476 | *mar_position = 0; |
477 | if (mar_buffer_seek(mar, mar_position, SIGNATURE_BLOCK_OFFSET) != 0) { |
478 | return -1; |
479 | } |
480 | |
481 | |
482 | if (mar_read_buffer(mar, &signatureCount, mar_position, |
483 | sizeof(signatureCount)) != 0) { |
484 | return -1; |
485 | } |
486 | signatureCount = ntohl(signatureCount); |
487 | |
488 | |
489 | |
490 | if (signatureCount > MAX_SIGNATURES) { |
491 | return -1; |
492 | } |
493 | |
494 | |
495 | for (i = 0; i < signatureCount; i++) { |
496 | |
497 | if (mar_buffer_seek(mar, mar_position, sizeof(uint32_t)) != 0) { |
498 | return -1; |
499 | } |
500 | |
501 | |
502 | if (mar_read_buffer(mar, &signatureLen, mar_position, sizeof(uint32_t)) != |
503 | 0) { |
504 | return -1; |
505 | } |
506 | signatureLen = ntohl(signatureLen); |
507 | if (mar_buffer_seek(mar, mar_position, signatureLen) != 0) { |
508 | return -1; |
509 | } |
510 | } |
511 | |
512 | if (*mar_position <= (size_t)INT64_MAX && |
513 | (int64_t)mar_position == (int64_t)offsetToContent) { |
514 | *hasAdditionalBlocks = 0; |
515 | } else { |
516 | if (numAdditionalBlocks) { |
517 | |
518 | |
519 | *hasAdditionalBlocks = 1; |
520 | if (mar_read_buffer(mar, numAdditionalBlocks, mar_position, |
521 | sizeof(uint32_t)) != 0) { |
522 | return -1; |
523 | } |
524 | *numAdditionalBlocks = ntohl(*numAdditionalBlocks); |
525 | if (offsetAdditionalBlocks) { |
526 | if (*mar_position > (size_t)UINT32_MAX) { |
527 | return -1; |
528 | } |
529 | *offsetAdditionalBlocks = (uint32_t)*mar_position; |
530 | } |
531 | } else if (offsetAdditionalBlocks) { |
532 | |
533 | |
534 | if (mar_buffer_seek(mar, mar_position, sizeof(uint32_t)) != 0) { |
535 | return -1; |
536 | } |
537 | if (*mar_position > (size_t)UINT32_MAX) { |
538 | return -1; |
539 | } |
540 | *offsetAdditionalBlocks = (uint32_t)*mar_position; |
541 | } |
542 | } |
543 | |
544 | return 0; |
545 | } |
546 | |
547 | |
548 | |
549 | |
550 | |
551 | |
552 | |
553 | |
554 | |
555 | int read_product_info_block(char* path, |
556 | struct ProductInformationBlock* infoBlock) { |
557 | int rv; |
558 | MarFile* mar; |
559 | MarReadResult result = mar_open(path, &mar); |
560 | if (result != MAR_READ_SUCCESS) { |
561 | fprintf(stderr, |
562 | "ERROR: could not open file in read_product_info_block()\n"); |
563 | return -1; |
564 | } |
565 | rv = mar_read_product_info_block(mar, infoBlock); |
566 | mar_close(mar); |
567 | return rv; |
568 | } |
569 | |
570 | |
571 | |
572 | |
573 | |
574 | |
575 | |
576 | |
577 | |
578 | int mar_read_product_info_block(MarFile* mar, |
579 | struct ProductInformationBlock* infoBlock) { |
580 | uint32_t offsetAdditionalBlocks, numAdditionalBlocks, additionalBlockSize, |
581 | additionalBlockID; |
582 | int hasAdditionalBlocks; |
583 | size_t mar_position = 0; |
584 | |
585 | |
586 | |
587 | char buf[MAXADDITIONALBLOCKSIZE + 1] = {'\0'}; |
588 | if (get_open_mar_file_info(mar, &mar_position, NULL, NULL, |
589 | &hasAdditionalBlocks, &offsetAdditionalBlocks, |
590 | &numAdditionalBlocks) != 0) { |
591 | return -1; |
592 | } |
593 | |
594 | |
595 | |
596 | if (numAdditionalBlocks > 0) { |
597 | |
598 | if (mar_read_buffer(mar, &additionalBlockSize, &mar_position, |
599 | sizeof(additionalBlockSize)) != 0) { |
600 | return -1; |
601 | } |
602 | additionalBlockSize = ntohl(additionalBlockSize) - |
603 | sizeof(additionalBlockSize) - |
604 | sizeof(additionalBlockID); |
605 | |
606 | |
607 | if (additionalBlockSize > MAXADDITIONALBLOCKSIZE) { |
608 | return -1; |
609 | } |
610 | |
611 | |
612 | if (mar_read_buffer(mar, &additionalBlockID, &mar_position, |
613 | sizeof(additionalBlockID)) != 0) { |
614 | return -1; |
615 | } |
616 | additionalBlockID = ntohl(additionalBlockID); |
617 | |
618 | if (PRODUCT_INFO_BLOCK_ID == additionalBlockID) { |
619 | const char* location; |
620 | int len; |
621 | |
622 | if (mar_read_buffer(mar, buf, &mar_position, additionalBlockSize) != 0) { |
623 | return -1; |
624 | } |
625 | |
626 | |
627 | |
628 | |
629 | location = buf; |
630 | len = strlen(location); |
631 | infoBlock->MARChannelID = location; |
632 | location += len + 1; |
633 | if (len >= 64) { |
634 | infoBlock->MARChannelID = NULL; |
635 | return -1; |
636 | } |
637 | |
638 | |
639 | len = strlen(location); |
640 | infoBlock->productVersion = location; |
641 | if (len >= 32) { |
642 | infoBlock->MARChannelID = NULL; |
643 | infoBlock->productVersion = NULL; |
644 | return -1; |
645 | } |
646 | infoBlock->MARChannelID = strdup(infoBlock->MARChannelID); |
647 | infoBlock->productVersion = strdup(infoBlock->productVersion); |
648 | return 0; |
649 | } else { |
650 | |
651 | if (mar_buffer_seek(mar, &mar_position, additionalBlockSize) != 0) { |
652 | return -1; |
653 | } |
654 | } |
655 | } |
656 | |
657 | |
658 | return -1; |
659 | } |
660 | |
661 | const MarItem* mar_find_item(MarFile* mar, const char* name) { |
662 | uint32_t hash; |
663 | const MarItem* item; |
664 | |
665 | if (!mar->item_table_is_valid) { |
666 | if (mar_read_index(mar)) { |
667 | return NULL; |
668 | } else { |
669 | mar->item_table_is_valid = 1; |
670 | } |
671 | } |
672 | |
673 | hash = mar_hash_name(name); |
674 | |
675 | item = mar->item_table[hash]; |
676 | while (item && strcmp(item->name, name) != 0) { |
677 | item = item->next; |
678 | } |
679 | |
680 | |
681 | if (mar_insert_offset(mar, item->offset, item->length) == 1) { |
682 | return item; |
683 | } else { |
684 | fprintf(stderr, "ERROR: file content collision in mar_find_item()\n"); |
685 | return NULL; |
686 | } |
687 | } |
688 | |
689 | int mar_enum_items(MarFile* mar, MarItemCallback callback, void* closure) { |
690 | MarItem* item; |
691 | int i, rv; |
692 | |
693 | if (!mar->item_table_is_valid) { |
694 | if (mar_read_index(mar)) { |
695 | return -1; |
696 | } else { |
697 | mar->item_table_is_valid = 1; |
698 | } |
699 | } |
700 | |
701 | for (i = 0; i < TABLESIZE; ++i) { |
702 | item = mar->item_table[i]; |
703 | while (item) { |
704 | |
705 | if (mar_insert_offset(mar, item->offset, item->length) == 1) { |
706 | rv = callback(mar, item, closure); |
707 | if (rv) { |
708 | return rv; |
709 | } |
710 | } else { |
711 | fprintf(stderr, "ERROR: file content collision in mar_enum_items()\n"); |
712 | return 1; |
713 | } |
714 | item = item->next; |
715 | } |
716 | } |
717 | |
718 | return 0; |
719 | } |
720 | |
721 | int mar_read(MarFile* mar, const MarItem* item, int offset, uint8_t* buf, |
722 | int bufsize) { |
723 | int nr; |
724 | size_t mar_position = 0; |
725 | |
726 | if (offset == (int)item->length) { |
727 | return 0; |
728 | } |
729 | if (offset > (int)item->length) { |
730 | return -1; |
731 | } |
732 | |
733 | nr = item->length - offset; |
734 | if (nr > bufsize) { |
735 | nr = bufsize; |
736 | } |
737 | |
738 | |
739 | if (mar_buffer_seek(mar, &mar_position, item->offset)) { |
740 | return -1; |
741 | } |
742 | if (mar_buffer_seek(mar, &mar_position, offset)) { |
743 | return -1; |
744 | } |
745 | |
746 | return mar_read_buffer_max(mar, buf, &mar_position, nr); |
747 | } |
748 | |
749 | |
750 | |
751 | |
752 | |
753 | |
754 | |
755 | |
756 | |
757 | |
758 | |
759 | |
760 | |
761 | |
762 | |
763 | |
764 | |
765 | |
766 | |
767 | int get_mar_file_info(const char* path, int* hasSignatureBlock, |
768 | uint32_t* numSignatures, int* hasAdditionalBlocks, |
769 | uint32_t* offsetAdditionalBlocks, |
770 | uint32_t* numAdditionalBlocks) { |
771 | int rv; |
772 | MarFile* mar; |
773 | size_t mar_position = 0; |
774 | MarReadResult result = mar_open(path, &mar); |
| |
775 | if (result != MAR_READ_SUCCESS) { |
776 | fprintf(stderr, "ERROR: could not read file in get_mar_file_info()\n"); |
777 | return -1; |
778 | } |
779 | |
780 | rv = get_open_mar_file_info(mar, &mar_position, hasSignatureBlock, |
781 | numSignatures, hasAdditionalBlocks, |
782 | offsetAdditionalBlocks, numAdditionalBlocks); |
783 | |
784 | mar_close(mar); |
785 | return rv; |
786 | } |