pak.c (20943B)
1 #define HEADER_IMPL 2 3 #include "pak.h" 4 5 #include <string.h> 6 #include <unistd.h> 7 #include <inttypes.h> 8 9 /* mem stream helper 10 * =========================================================================== 11 */ 12 13 struct pak_mem_stream { 14 uint8_t *buf, *end, *cur; 15 }; 16 17 static inline size_t 18 pak_mem_stream_bytes_remaining(struct pak_mem_stream const *stream) 19 { 20 assert(stream->cur <= stream->end); 21 return stream->end - stream->cur; 22 } 23 24 static inline size_t 25 pak_mem_stream_bytes_consumed(struct pak_mem_stream const *stream) 26 { 27 assert(stream->buf <= stream->cur); 28 return stream->cur - stream->buf; 29 } 30 31 static inline void 32 pak_mem_stream_reset(struct pak_mem_stream *stream) 33 { 34 stream->cur = stream->buf; 35 } 36 37 static inline void * 38 pak_mem_stream_skip(struct pak_mem_stream *stream, size_t bytes) 39 { 40 assert(stream->cur + bytes <= stream->end); 41 void *ptr = stream->cur; 42 stream->cur += bytes; 43 return ptr; 44 } 45 46 static inline void 47 pak_mem_stream_readu8(struct pak_mem_stream *stream, uint8_t *out) 48 { 49 assert(stream->cur + sizeof(uint8_t) <= stream->end); 50 uint8_t res = *(stream->cur++); 51 *out = res; 52 stream->cur += sizeof *out; 53 } 54 55 static inline void 56 pak_mem_stream_readu16(struct pak_mem_stream *stream, uint16_t *out) 57 { 58 assert(stream->cur + sizeof(uint16_t) <= stream->end); 59 uint16_t res = *((uint16_t *) stream->cur); 60 *out = res; 61 stream->cur += sizeof *out; 62 } 63 64 static inline void 65 pak_mem_stream_readu32(struct pak_mem_stream *stream, uint32_t *out) 66 { 67 assert(stream->cur + sizeof(uint32_t) <= stream->end); 68 uint32_t res = *((uint32_t *) stream->cur); 69 *out = res; 70 stream->cur += sizeof *out; 71 } 72 73 static inline void 74 pak_mem_stream_readu64(struct pak_mem_stream *stream, uint64_t *out) 75 { 76 assert(stream->cur + sizeof(uint64_t) <= stream->end); 77 uint64_t res = *((uint64_t *) stream->cur); 78 *out = res; 79 stream->cur += sizeof *out; 80 } 81 82 static inline void 83 pak_mem_stream_readbuf(struct pak_mem_stream *stream, void *buf, size_t len) 84 { 85 assert(stream->cur + len <= stream->end); 86 memcpy(buf, stream->cur, len); 87 stream->cur += len; 88 } 89 90 #define PAK_MEM_STREAM_READ(stream, var) \ 91 _Generic((var), \ 92 uint8_t: pak_mem_stream_readu8, \ 93 uint16_t: pak_mem_stream_readu16, \ 94 uint32_t: pak_mem_stream_readu32, \ 95 uint64_t: pak_mem_stream_readu64 \ 96 )((stream), &(var)) 97 98 static inline void 99 pak_mem_stream_writeu8(struct pak_mem_stream *stream, uint8_t val) 100 { 101 assert(stream->cur + sizeof(uint8_t) <= stream->end); 102 *(stream->cur++) = val; 103 stream->cur += sizeof val; 104 } 105 106 static inline void 107 pak_mem_stream_writeu16(struct pak_mem_stream *stream, uint16_t val) 108 { 109 assert(stream->cur + sizeof(uint16_t) <= stream->end); 110 *((uint16_t *) stream->cur) = val; 111 stream->cur += sizeof val; 112 } 113 114 static inline void 115 pak_mem_stream_writeu32(struct pak_mem_stream *stream, uint32_t val) 116 { 117 assert(stream->cur + sizeof(uint32_t) <= stream->end); 118 *((uint32_t *) stream->cur) = val; 119 stream->cur += sizeof val; 120 } 121 122 static inline void 123 pak_mem_stream_writeu64(struct pak_mem_stream *stream, uint64_t val) 124 { 125 assert(stream->cur + sizeof(uint64_t) <= stream->end); 126 *((uint64_t *) stream->cur) = val; 127 stream->cur += sizeof val; 128 } 129 130 static inline void 131 pak_mem_stream_writebuf(struct pak_mem_stream *stream, void const *buf, size_t len) 132 { 133 assert(stream->cur + len <= stream->end); 134 memcpy(stream->cur, buf, len); 135 stream->cur += len; 136 } 137 138 #define PAK_MEM_STREAM_WRITE(stream, var) \ 139 _Generic((var), \ 140 uint8_t: pak_mem_stream_writeu8, \ 141 uint16_t: pak_mem_stream_writeu16, \ 142 uint32_t: pak_mem_stream_writeu32, \ 143 uint64_t: pak_mem_stream_writeu64 \ 144 )((stream), (var)) 145 146 /* =========================================================================== 147 */ 148 149 static int 150 pak_write_mem_header(struct pak_mem_stream *stream, struct pakfmt_header const *hdr) 151 { 152 if (pak_mem_stream_bytes_remaining(stream) < PAK_HEADER_SIZE) 153 return-1; 154 155 pak_mem_stream_writebuf(stream, PAK_MAGIC, PAK_MAGIC_LEN); 156 PAK_MEM_STREAM_WRITE(stream, hdr->header_length); 157 158 PAK_MEM_STREAM_WRITE(stream, hdr->index_file_offset); 159 PAK_MEM_STREAM_WRITE(stream, hdr->index_compression); 160 PAK_MEM_STREAM_WRITE(stream, hdr->index_compressed_length); 161 PAK_MEM_STREAM_WRITE(stream, hdr->index_uncompressed_length); 162 PAK_MEM_STREAM_WRITE(stream, hdr->index_uncompressed_crc32c); 163 164 PAK_MEM_STREAM_WRITE(stream, hdr->data_file_offset); 165 PAK_MEM_STREAM_WRITE(stream, hdr->data_compressed_length); 166 167 return 0; 168 } 169 170 static int 171 pak_write_mem_tag(struct pak_mem_stream *stream, struct pak_tag const *tag) 172 { 173 if (pak_mem_stream_bytes_remaining(stream) < PAK_TAG_SIZE) 174 return -1; 175 176 pak_mem_stream_writebuf(stream, tag->header.name, sizeof tag->header.name); 177 PAK_MEM_STREAM_WRITE(stream, tag->header.type); 178 PAK_MEM_STREAM_WRITE(stream, tag->header.length); 179 180 if (pak_mem_stream_bytes_remaining(stream) < tag->header.length) 181 return -1; 182 183 pak_mem_stream_writebuf(stream, tag->data, tag->header.length); 184 185 return 0; 186 } 187 188 static int 189 pak_write_mem_archive(struct pak_mem_stream *stream, struct pak_archive const *archive) 190 { 191 if (pak_mem_stream_bytes_remaining(stream) < PAK_ARCHIVE_SIZE) 192 return -1; 193 194 pak_mem_stream_writebuf(stream, archive->header.name, sizeof archive->header.name); 195 PAK_MEM_STREAM_WRITE(stream, archive->header.type); 196 PAK_MEM_STREAM_WRITE(stream, archive->header.length); 197 198 size_t archive_bytes_remaining = archive->header.length - PAK_ARCHIVE_PRELUDE_SIZE; 199 if (pak_mem_stream_bytes_remaining(stream) < archive_bytes_remaining) 200 return -1; 201 202 PAK_MEM_STREAM_WRITE(stream, archive->header.data_offset); 203 PAK_MEM_STREAM_WRITE(stream, archive->header.data_compressed_length); 204 PAK_MEM_STREAM_WRITE(stream, archive->header.data_uncompressed_length); 205 PAK_MEM_STREAM_WRITE(stream, archive->header.data_uncompressed_crc32c); 206 PAK_MEM_STREAM_WRITE(stream, archive->header.data_compression); 207 208 PAK_MEM_STREAM_WRITE(stream, archive->header.reserved); 209 PAK_MEM_STREAM_WRITE(stream, archive->header.tag_count); 210 211 struct pak_tag *tag; 212 LIST_ENTRY_ITER(&archive->tags, tag, list_node) { 213 if (pak_write_mem_tag(stream, tag) < 0) 214 return -1; 215 } 216 217 return 0; 218 } 219 220 static int 221 pak_write_mem_archive_data(struct pak_mem_stream *stream, struct pak_archive const *archive) 222 { 223 if (pak_mem_stream_bytes_remaining(stream) < archive->header.data_offset) 224 return -1; 225 226 pak_mem_stream_skip(stream, archive->header.data_offset); 227 228 assert(archive->header.data_compression == PAK_COMPRESSION_NONE); 229 assert(archive->header.data_compressed_length == archive->header.data_uncompressed_length); 230 231 if (pak_mem_stream_bytes_remaining(stream) < archive->header.data_compressed_length) 232 return -1; 233 234 pak_mem_stream_writebuf(stream, archive->data, archive->header.data_compressed_length); 235 236 return 0; 237 } 238 239 static int 240 pak_write_mem_index(struct pak_mem_stream *stream, struct list_node const *index) 241 { 242 struct pak_archive *it; 243 LIST_ENTRY_ITER(index, it, list_node) { 244 if (pak_write_mem_archive(stream, it) < 0) 245 return -1; 246 } 247 248 return 0; 249 } 250 251 static int 252 pak_read_mem_header(struct pak_mem_stream *stream, struct pakfmt_header *hdr) 253 { 254 if (pak_mem_stream_bytes_remaining(stream) < PAK_HEADER_SIZE) 255 return -1; 256 257 pak_mem_stream_readbuf(stream, hdr->magic, sizeof hdr->magic); 258 if (strncmp(PAK_MAGIC, hdr->magic, sizeof hdr->magic)) 259 return -1; 260 261 PAK_MEM_STREAM_READ(stream, hdr->header_length); 262 if (hdr->header_length != PAK_HEADER_SIZE) 263 return -1; 264 265 PAK_MEM_STREAM_READ(stream, hdr->index_file_offset); 266 PAK_MEM_STREAM_READ(stream, hdr->index_compression); 267 PAK_MEM_STREAM_READ(stream, hdr->index_compressed_length); 268 PAK_MEM_STREAM_READ(stream, hdr->index_uncompressed_length); 269 PAK_MEM_STREAM_READ(stream, hdr->index_uncompressed_crc32c); 270 271 PAK_MEM_STREAM_READ(stream, hdr->data_file_offset); 272 PAK_MEM_STREAM_READ(stream, hdr->data_compressed_length); 273 274 return 0; 275 } 276 277 static struct pak_tag * 278 pak_read_mem_tag(struct pak_mem_stream *stream, struct arena *arena) 279 { 280 struct pak_tag *res = ARENA_ALLOC_SIZED(arena, struct pak_tag); 281 if (!res) return NULL; 282 283 memset(res, 0, sizeof *res); 284 285 if (pak_mem_stream_bytes_remaining(stream) < PAK_TAG_SIZE) 286 return NULL; 287 288 pak_mem_stream_readbuf(stream, res->header.name, sizeof res->header.name); 289 PAK_MEM_STREAM_READ(stream, res->header.type); 290 PAK_MEM_STREAM_READ(stream, res->header.length); 291 292 if (pak_mem_stream_bytes_remaining(stream) < res->header.length) 293 return NULL; 294 295 res->data = pak_mem_stream_skip(stream, res->header.length); 296 297 return res; 298 } 299 300 static struct pak_archive * 301 pak_read_mem_archive(struct pak_mem_stream *stream, struct arena *arena) 302 { 303 struct pak_archive *res = ARENA_ALLOC_SIZED(arena, struct pak_archive); 304 if (!res) return NULL; 305 306 memset(res, 0, sizeof *res); 307 308 if (pak_mem_stream_bytes_remaining(stream) < PAK_ARCHIVE_SIZE) 309 return NULL; 310 311 pak_mem_stream_readbuf(stream, res->header.name, sizeof res->header.name); 312 PAK_MEM_STREAM_READ(stream, res->header.type); 313 PAK_MEM_STREAM_READ(stream, res->header.length); 314 315 size_t archive_bytes_remaining = res->header.length - PAK_ARCHIVE_PRELUDE_SIZE; 316 if (pak_mem_stream_bytes_remaining(stream) < archive_bytes_remaining) 317 return NULL; 318 319 PAK_MEM_STREAM_READ(stream, res->header.data_offset); 320 PAK_MEM_STREAM_READ(stream, res->header.data_compressed_length); 321 PAK_MEM_STREAM_READ(stream, res->header.data_uncompressed_length); 322 PAK_MEM_STREAM_READ(stream, res->header.data_uncompressed_crc32c); 323 PAK_MEM_STREAM_READ(stream, res->header.data_compression); 324 325 PAK_MEM_STREAM_READ(stream, res->header.reserved); 326 PAK_MEM_STREAM_READ(stream, res->header.tag_count); 327 328 res->tags = LIST_INIT(res->tags); 329 for (uint32_t i = 0; i < res->header.tag_count; i++) { 330 struct pak_tag *ent = pak_read_mem_tag(stream, arena); 331 if (!ent) return NULL; 332 333 list_push_tail(&res->tags, &ent->list_node); 334 } 335 336 return res; 337 } 338 339 static int 340 pak_read_mem_archive_data(struct pak_mem_stream *stream, struct pak_archive *archive) 341 { 342 if (pak_mem_stream_bytes_remaining(stream) < archive->header.data_offset) 343 return -1; 344 345 pak_mem_stream_skip(stream, archive->header.data_offset); 346 347 if (pak_mem_stream_bytes_remaining(stream) < archive->header.data_compressed_length) 348 return -1; 349 350 archive->data = pak_mem_stream_skip(stream, archive->header.data_compressed_length); 351 352 return 0; 353 } 354 355 static int 356 pak_read_mem_index(struct pak_mem_stream *stream, struct arena *arena, struct list_node *index) 357 { 358 while (pak_mem_stream_bytes_remaining(stream)) { 359 struct pak_archive *ent = pak_read_mem_archive(stream, arena); 360 if (!ent) return -1; 361 362 list_push_tail(index, &ent->list_node); 363 } 364 365 return 0; 366 } 367 368 /* =========================================================================== 369 */ 370 371 int 372 pak_read_header(int fd, struct pakfmt_header *out) 373 { 374 if (lseek(fd, 0, SEEK_SET) < 0) 375 return -1; 376 377 ssize_t bytes_read = 0; 378 if ((bytes_read = read(fd, out, sizeof *out)) < 0) 379 return -1; 380 381 if ((size_t) bytes_read < sizeof *out) 382 return -1; 383 384 return 0; 385 } 386 387 int 388 pak_read_index(int fd, struct arena *arena, struct pakfmt_header const *hdr, 389 uint8_t *buf, size_t len, struct list_node *index) 390 { 391 /* TODO: this assumes we can always do in-place decompression. 392 * is this the case? 393 */ 394 assert(hdr->index_uncompressed_length <= len); 395 396 int res = -1; 397 398 if (lseek(fd, hdr->index_file_offset, SEEK_SET) < 0) 399 goto error; 400 401 ssize_t bytes_read = 0; 402 if ((bytes_read = read(fd, buf, hdr->index_compressed_length)) < 0) 403 goto error; 404 405 if ((size_t) bytes_read < hdr->index_compressed_length) 406 goto error; 407 408 /* TODO: implement decompression */ 409 assert(hdr->index_compression == PAK_COMPRESSION_NONE); 410 assert(hdr->index_compressed_length == hdr->index_uncompressed_length); 411 412 struct pak_mem_stream stream = { 413 .buf = buf, .end = buf + hdr->index_uncompressed_length, .cur = buf, 414 }; 415 416 res = pak_read_mem_index(&stream, arena, index); 417 418 error: 419 return res; 420 } 421 422 int 423 pak_read_archive(int fd, struct arena *arena, struct pakfmt_header const *hdr, 424 char name[static PAK_ARCHIVE_NAME_LEN], uint32_t type, 425 struct pak_archive **out) 426 { 427 uint8_t prelude[PAK_ARCHIVE_PRELUDE_SIZE]; 428 429 int res = -1; 430 431 if (lseek(fd, hdr->index_file_offset, SEEK_SET) < 0) 432 goto error; 433 434 do { 435 ssize_t bytes_read = 0; 436 if ((bytes_read = read(fd, prelude, sizeof prelude)) < 0) 437 goto error; 438 439 if ((size_t) bytes_read < sizeof prelude) 440 goto error; 441 442 // we want to simply access the first few fields in the 443 // archive (the "prelude"), and so casting is fine as long 444 // as we don't overrun our prelude buffer 445 struct pakfmt_archive *archive = (struct pakfmt_archive *) prelude; 446 size_t archive_bytes_remaining = archive->length - PAK_ARCHIVE_PRELUDE_SIZE; 447 448 if (strncmp(name, archive->name, sizeof archive->name)) 449 goto skip; 450 451 if (archive->type != type) 452 goto skip; 453 454 // read rest of archive 455 uint8_t *buf = arena_alloc(arena, archive->length, alignof(struct pak_archive)); 456 if (!buf) 457 goto error; 458 459 lseek(fd, -PAK_ARCHIVE_PRELUDE_SIZE, SEEK_CUR); 460 461 if ((bytes_read = read(fd, buf, archive->length)) < 0) 462 goto error; 463 464 if ((size_t) bytes_read < archive->length) 465 goto error; 466 467 struct pak_mem_stream stream = { 468 .buf = buf, .end = buf + archive->length, .cur = buf, 469 }; 470 471 *out = pak_read_mem_archive(&stream, arena); 472 if (!*out) 473 goto error; 474 475 res = 0; 476 477 break; 478 479 skip: 480 if (lseek(fd, archive_bytes_remaining, SEEK_CUR) < 0) 481 goto error; 482 } while (1); 483 484 error: 485 return res; 486 } 487 488 int 489 pak_read_archive_data(int fd, struct pakfmt_header const *hdr, 490 struct pakfmt_archive const *archive, 491 uint8_t *buf, size_t len) 492 { 493 assert(archive->data_compressed_length <= len); 494 495 if (lseek(fd, hdr->data_file_offset + archive->data_offset, SEEK_SET) < 0) 496 return -1; 497 498 ssize_t bytes_read = 0; 499 if ((bytes_read = read(fd, buf, archive->data_compressed_length)) < 0) 500 return -1; 501 502 if ((size_t) bytes_read < archive->data_compressed_length) 503 return -1; 504 505 return 0; 506 } 507 508 int 509 pak_write(int fd, struct pak const *pak) 510 { 511 int res = -1; 512 void *buf = NULL; 513 514 size_t serialised_size = pak_file_size(pak); 515 buf = malloc(serialised_size); 516 if (!buf) 517 goto error; 518 519 if (pak_write_mem(buf, serialised_size, pak) < 0) 520 goto error; 521 522 size_t written = write(fd, buf, serialised_size); 523 if (written < serialised_size) 524 goto error; 525 526 res = 0; 527 528 error: 529 free(buf); 530 531 return res; 532 } 533 534 int 535 pak_write_mem(uint8_t *buf, size_t len, struct pak const *pak) 536 { 537 struct pak_mem_stream stream = { 538 .buf = buf, .end = buf + len, .cur = buf, 539 }; 540 541 if (pak_write_mem_header(&stream, &pak->header) < 0) 542 return -1; 543 544 uint8_t *index_buf = buf + pak->header.index_file_offset; 545 uint8_t *index_buf_end = index_buf + pak->header.index_compressed_length; 546 uint8_t *data_buf = buf + pak->header.data_file_offset; 547 uint8_t *data_buf_end = data_buf + pak->header.data_compressed_length; 548 549 struct pak_mem_stream index_stream = { 550 .buf = index_buf, .end = index_buf_end, .cur = index_buf, 551 }; 552 553 if (pak_write_mem_index(&index_stream, &pak->index) < 0) 554 return -1; 555 556 struct pak_mem_stream data_stream = { 557 .buf = data_buf, .end = data_buf_end, .cur = data_buf, 558 }; 559 560 struct pak_archive *it; 561 LIST_ENTRY_ITER(&pak->index, it, list_node) { 562 pak_mem_stream_reset(&data_stream); 563 if (pak_write_mem_archive_data(&data_stream, it) < 0) 564 return -1; 565 } 566 567 return 0; 568 } 569 570 int 571 pak_read_mem(uint8_t *buf, size_t len, struct arena *arena, struct pak *pak) 572 { 573 struct pak_mem_stream stream = { 574 .buf = buf, .end = buf + len, .cur = buf, 575 }; 576 577 if (pak_read_mem_header(&stream, &pak->header) < 0) 578 return -1; 579 580 uint8_t *buf_end = buf + len; 581 uint8_t *index_buf = buf + pak->header.index_file_offset; 582 uint8_t *index_buf_end = index_buf + pak->header.index_compressed_length; 583 uint8_t *data_buf = buf + pak->header.data_file_offset; 584 uint8_t *data_buf_end = data_buf + pak->header.data_compressed_length; 585 586 if (index_buf_end > buf_end || data_buf_end > buf_end) 587 return -1; 588 589 pak->index = LIST_INIT(pak->index); 590 591 struct pak_mem_stream index_stream = { 592 .buf = index_buf, .end = index_buf_end, .cur = index_buf, 593 }; 594 595 if (pak_read_mem_index(&index_stream, arena, &pak->index) < 0) 596 return -1; 597 598 struct pak_mem_stream data_stream = { 599 .buf = data_buf, .end = data_buf_end, .cur = data_buf, 600 }; 601 602 struct pak_archive *it; 603 LIST_ENTRY_ITER(&pak->index, it, list_node) { 604 pak_mem_stream_reset(&data_stream); 605 if (pak_read_mem_archive_data(&data_stream, it)) 606 return -1; 607 } 608 609 return 0; 610 } 611 612 void 613 pak_open(struct pak *pak) 614 { 615 memcpy(pak->header.magic, PAK_MAGIC, sizeof pak->header.magic); 616 pak->header.header_length = sizeof pak->header; 617 618 pak->header.index_file_offset = 0; 619 pak->header.index_compression = PAK_COMPRESSION_NONE; 620 pak->header.index_compressed_length = 0; 621 pak->header.index_uncompressed_length = 0; 622 pak->header.index_uncompressed_crc32c = 0; 623 624 pak->header.data_file_offset = 0; 625 pak->header.data_compressed_length = 0; 626 627 pak->index = LIST_INIT(pak->index); 628 } 629 630 struct pak_archive * 631 pak_add_archive(struct pak *pak, struct arena *arena, 632 char name[static PAK_ARCHIVE_NAME_LEN], uint32_t type, 633 enum pak_compression_type compression, 634 struct pak_tag *tags, size_t tags_count, 635 void *data, size_t compressed_length, 636 size_t uncompressed_length, uint32_t uncompressed_crc32c) 637 { 638 struct pak_archive *archive = ARENA_ALLOC_SIZED(arena, struct pak_archive); 639 if (!archive) return NULL; 640 641 memset(archive, 0, sizeof *archive); 642 643 memcpy(archive->header.name, name, sizeof archive->header.name); 644 archive->header.type = type; 645 archive->header.length = PAK_ARCHIVE_SIZE; 646 647 archive->header.data_compressed_length = compressed_length; 648 archive->header.data_uncompressed_length = uncompressed_length; 649 archive->header.data_uncompressed_crc32c = uncompressed_crc32c; 650 archive->header.data_compression = compression; 651 652 archive->header.tag_count = tags_count; 653 654 archive->tags = LIST_INIT(archive->tags); 655 for (size_t i = 0; i < tags_count; i++) { 656 struct pak_tag *tag = ARENA_ALLOC_SIZED(arena, struct pak_tag); 657 if (!tag) return NULL; 658 659 memset(tag, 0, sizeof *tag); 660 661 memcpy(tag->header.name, tags[i].header.name, sizeof tag->header.name); 662 tag->header.type = tags[i].header.type; 663 tag->header.length = tags[i].header.length; 664 665 tag->data = tags[i].data; 666 667 list_push_tail(&archive->tags, &tag->list_node); 668 669 archive->header.length += PAK_TAG_SIZE + tag->header.length; 670 } 671 672 archive->data = data; 673 674 list_push_tail(&pak->index, &archive->list_node); 675 676 return archive; 677 } 678 679 void 680 pak_close(struct pak *pak) 681 { 682 pak->header.index_file_offset = pak->header.header_length; 683 684 pak->header.index_compressed_length = 0; 685 pak->header.data_compressed_length = 0; 686 687 struct pak_archive *it; 688 LIST_ENTRY_ITER(&pak->index, it, list_node) { 689 pak->header.index_uncompressed_length += it->header.length; 690 pak->header.index_uncompressed_crc32c = 0; /* TODO: calculate crc32c */ 691 692 it->header.data_offset = pak->header.data_compressed_length; 693 pak->header.data_compressed_length += it->header.data_compressed_length; 694 } 695 696 assert(pak->header.index_compression == PAK_COMPRESSION_NONE); /* TODO: index compression */ 697 pak->header.index_compressed_length = pak->header.index_uncompressed_length; 698 pak->header.data_file_offset = pak->header.index_file_offset + pak->header.index_compressed_length; 699 } 700 701 void 702 pak_debug_dump(struct pak const *pak) 703 { 704 printf("pak header:\n"); 705 printf("\tlength: %" PRIu32 "\n", pak->header.header_length); 706 printf("\tindex file offset: %" PRIu64 "\n", pak->header.index_file_offset); 707 printf("\tindex compression: %" PRIu32 "\n", pak->header.index_compression); 708 printf("\tindex compressed length: %" PRIu32 "\n", pak->header.index_compressed_length); 709 printf("\tindex uncompressed length: %" PRIu32 "\n", pak->header.index_uncompressed_length); 710 printf("\tindex uncompressed CRC32c: %" PRIu32 "\n", pak->header.index_uncompressed_crc32c); 711 printf("\tdata file offset: %" PRIu64 "\n", pak->header.data_file_offset); 712 printf("\tdata compressed length: %" PRIu64 "\n", pak->header.data_compressed_length); 713 714 printf("pak index:\n"); 715 716 size_t i = 0; 717 718 struct pak_archive *it; 719 LIST_ENTRY_ITER(&pak->index, it, list_node) { 720 printf("\tarchive %zu:\n", i++); 721 printf("\t\tname: \"%.*s\"\n", (int) sizeof it->header.name, it->header.name); 722 printf("\t\tarchive type: %" PRIu32 "\n", it->header.type); 723 printf("\t\tarchive length: %" PRIu32 "\n", it->header.length); 724 printf("\t\tdata offset: %" PRIu64 "\n", it->header.data_offset); 725 printf("\t\tdata compressed length: %" PRIu64 "\n", it->header.data_compressed_length); 726 printf("\t\tdata uncompressed length: %" PRIu64 "\n", it->header.data_uncompressed_length); 727 printf("\t\tdata uncompressed CRC32c: %" PRIu32 "\n", it->header.data_uncompressed_crc32c); 728 printf("\t\tdata compression: %" PRIu32 "\n", it->header.data_compression); 729 printf("\t\ttag count: %" PRIu32 "\n", it->header.tag_count); 730 731 printf("\t\tarchive tags:\n"); 732 733 size_t j = 0; 734 735 struct pak_tag *tag; 736 LIST_ENTRY_ITER(&it->tags, tag, list_node) { 737 printf("\t\t\ttag %zu:\n", j++); 738 printf("\t\t\t\ttag name: \"%.*s\"\n", (int) sizeof tag->header.name, tag->header.name); 739 printf("\t\t\t\ttag type: %" PRIu16 "\n", tag->header.type); 740 printf("\t\t\t\ttag length: %" PRIu16 "\n", tag->header.length); 741 } 742 743 printf("\t\tarchive data: %p\n", it->data); 744 } 745 }