Mercurial > hg > dmlib
comparison tools/packed.c @ 2480:c7a0913e1032
Various cleanups, integrate some changes/improvements from opendat project to packed.
author | Matti Hamalainen <ccr@tnsp.org> |
---|---|
date | Mon, 27 Apr 2020 21:37:15 +0300 |
parents | c1cae47cd410 |
children | c64806412be0 |
comparison
equal
deleted
inserted
replaced
2479:c1cae47cd410 | 2480:c7a0913e1032 |
---|---|
27 enum | 27 enum |
28 { | 28 { |
29 PACK_EXTRACTED = 0x0001, | 29 PACK_EXTRACTED = 0x0001, |
30 }; | 30 }; |
31 | 31 |
32 int nsrcFilenames = 0, nexcFilenames = 0; | 32 |
33 size_t nsrcFilenames = 0, nexcFilenames = 0; | |
33 char * srcFilenames[SET_MAX_FILES]; | 34 char * srcFilenames[SET_MAX_FILES]; |
34 char * excFilenames[SET_MAX_FILES]; | 35 char * excFilenames[SET_MAX_FILES]; |
35 | 36 |
36 char * optPackFilename = NULL; | 37 char * optPackFilename = NULL; |
37 BOOL optDoCompress = TRUE; | |
38 int optCompressLevel = Z_BEST_COMPRESSION; | 38 int optCompressLevel = Z_BEST_COMPRESSION; |
39 int optCommand = CMD_NONE; | 39 int optCommand = CMD_NONE; |
40 int optDefResFlags = 0; | |
41 | 40 |
42 | 41 |
43 static const DMOptArg cmdList[] = | 42 static const DMOptArg cmdList[] = |
44 { | 43 { |
45 { CMD_CREATE , 'c', "create", "Create and add files to PACK", OPT_NONE }, | 44 { CMD_CREATE , 'c', "create", "Create and add files to PACK", OPT_NONE }, |
55 { | 54 { |
56 { 0, '?', "help" , "Show this help", OPT_NONE }, | 55 { 0, '?', "help" , "Show this help", OPT_NONE }, |
57 { 1, 0, "license" , "Print out this program's license agreement", OPT_NONE }, | 56 { 1, 0, "license" , "Print out this program's license agreement", OPT_NONE }, |
58 { 2, 'v', "verbose" , "Be more verbose", OPT_NONE }, | 57 { 2, 'v', "verbose" , "Be more verbose", OPT_NONE }, |
59 | 58 |
60 { 3, 'n', "nocompress" , "No compression / decompression", OPT_NONE }, | 59 { 4, 'C', "level" , "Set zlib compression level 0-9", OPT_ARGREQ }, |
61 { 4, 'C', "level" , "Set zlib compression level 1-9", OPT_ARGREQ }, | |
62 { 5, 'f', "resflags" , "Set default resource flags (-f 0xff)", OPT_ARGREQ }, | |
63 { 6, 'x', "exclude" , "Exclude name/glob pattern", OPT_ARGREQ }, | 60 { 6, 'x', "exclude" , "Exclude name/glob pattern", OPT_ARGREQ }, |
64 }; | 61 }; |
65 | 62 |
66 static const int optListN = sizeof(optList) / sizeof(optList[0]); | 63 static const int optListN = sizeof(optList) / sizeof(optList[0]); |
67 | 64 |
114 | 111 |
115 case 2: | 112 case 2: |
116 dmVerbosity++; | 113 dmVerbosity++; |
117 break; | 114 break; |
118 | 115 |
119 case 3: | |
120 optDoCompress = FALSE; | |
121 break; | |
122 | |
123 case 4: | 116 case 4: |
124 optCompressLevel = atoi(optArg); | 117 optCompressLevel = atoi(optArg); |
125 if (optCompressLevel < 1 || optCompressLevel > 9) | 118 if (optCompressLevel < 0 || optCompressLevel > 9) |
126 { | 119 { |
127 dmErrorMsg("Invalid compression level argument '%s', must be 1 .. 9.\n", optArg); | 120 dmErrorMsg("Invalid compression level argument '%s', must be 0 .. 9.\n", optArg); |
128 return FALSE; | 121 return FALSE; |
129 } | |
130 break; | |
131 | |
132 case 5: | |
133 { | |
134 unsigned int tmpUI; | |
135 if (!dmGetIntVal(optArg, &tmpUI, NULL)) | |
136 { | |
137 dmErrorMsg("Invalid flags value '%s'.\n", optArg); | |
138 return FALSE; | |
139 } | |
140 optDefResFlags = tmpUI; | |
141 } | 122 } |
142 break; | 123 break; |
143 | 124 |
144 case 6: | 125 case 6: |
145 if (nexcFilenames < SET_MAX_FILES) | 126 if (nexcFilenames < SET_MAX_FILES) |
204 } | 185 } |
205 | 186 |
206 | 187 |
207 DMPackEntry *dmPackEntryCopy(const DMPackEntry *src) | 188 DMPackEntry *dmPackEntryCopy(const DMPackEntry *src) |
208 { | 189 { |
209 DMPackEntry *node = dmPackEntryNew(); | 190 DMPackEntry *entry = dmPackEntryNew(); |
210 if (node == NULL) | 191 if (entry == NULL) |
211 return NULL; | 192 return NULL; |
212 | 193 |
213 strncpy(node->filename, src->filename, DMRES_NAME_LEN); | 194 strncpy(entry->filename, src->filename, DMRES_NAME_LEN); |
214 node->filename[DMRES_NAME_LEN] = 0; | 195 entry->filename[DMRES_NAME_LEN] = 0; |
215 | 196 |
216 node->size = src->size; | 197 entry->size = src->size; |
217 node->offset = src->offset; | 198 entry->offset = src->offset; |
218 node->csize = src->csize; | 199 entry->csize = src->csize; |
219 node->flags = src->flags; | 200 entry->flags = src->flags; |
220 | 201 |
221 return node; | 202 return entry; |
222 } | 203 } |
223 | 204 |
224 | 205 |
225 int dmPackWrite(DMPackFile * pack) | 206 int dmPackWrite(DMPackFile * pack) |
226 { | 207 { |
227 DMPackEntry *node; | 208 DMPackEntry *entry; |
228 DMPackFileHeader hdr; | 209 DMPackFileHeader hdr; |
229 | 210 |
230 if (pack == NULL) | 211 if (pack == NULL) |
231 return DMERR_OK; | 212 return DMERR_OK; |
232 | 213 |
239 hdr.dirEntries = 0; | 220 hdr.dirEntries = 0; |
240 hdr.dirOffset = | 221 hdr.dirOffset = |
241 sizeof(hdr.ident) + sizeof(hdr.version) + | 222 sizeof(hdr.ident) + sizeof(hdr.version) + |
242 sizeof(hdr.dirEntries) + sizeof(hdr.dirOffset); | 223 sizeof(hdr.dirEntries) + sizeof(hdr.dirOffset); |
243 | 224 |
244 for (node = pack->entries; node != NULL; node = node->next) | 225 for (entry = pack->entries; entry != NULL; entry = entry->next) |
245 { | 226 { |
246 hdr.dirEntries++; | 227 hdr.dirEntries++; |
247 hdr.dirOffset += node->csize; | 228 hdr.dirOffset += entry->csize; |
248 } | 229 } |
249 | 230 |
250 dmMsg(1, "%d entries in PACK, dir at offset 0x%08" DM_PRIx64 ".\n", | 231 dmMsg(1, "%d entries in PACK, dir at offset 0x%08" DM_PRIx64 ".\n", |
251 hdr.dirEntries, hdr.dirOffset); | 232 hdr.dirEntries, hdr.dirOffset); |
252 | 233 |
262 | 243 |
263 // Write the directory | 244 // Write the directory |
264 if (fseeko(pack->file, hdr.dirOffset, SEEK_SET) != 0) | 245 if (fseeko(pack->file, hdr.dirOffset, SEEK_SET) != 0) |
265 return DMERR_FSEEK; | 246 return DMERR_FSEEK; |
266 | 247 |
267 for (node = pack->entries; node != NULL; node = node->next) | 248 for (entry = pack->entries; entry != NULL; entry = entry->next) |
268 { | 249 { |
269 // Write one entry | 250 // Write one entry |
270 if (!dm_fwrite_str(pack->file, node->filename, DMRES_NAME_LEN) || | 251 if (!dm_fwrite_str(pack->file, entry->filename, DMRES_NAME_LEN) || |
271 !dm_fwrite_le64(pack->file, node->offset) || | 252 !dm_fwrite_le64(pack->file, entry->offset) || |
272 !dm_fwrite_le32(pack->file, node->csize) || | 253 !dm_fwrite_le32(pack->file, entry->csize) || |
273 !dm_fwrite_le32(pack->file, node->size) || | 254 !dm_fwrite_le32(pack->file, entry->size) || |
274 !dm_fwrite_le32(pack->file, node->flags)) | 255 !dm_fwrite_le32(pack->file, entry->flags)) |
275 return DMERR_FWRITE; | 256 return DMERR_FWRITE; |
276 } | 257 } |
277 | 258 |
278 return DMERR_OK; | 259 return DMERR_OK; |
279 } | 260 } |
280 | 261 |
281 | 262 |
282 int dmPackCreate(const char *filename, DMPackFile ** pack) | 263 int dmPackCreate(const char *filename, DMPackFile ** pack) |
283 { | 264 { |
284 // Allocate packfile-structure | 265 // Allocate packfile-structure |
285 *pack = (DMPackFile *) dmMalloc0(sizeof(DMPackFile)); | 266 if ((*pack = (DMPackFile *) dmMalloc0(sizeof(DMPackFile))) == NULL) |
286 if (*pack == NULL) | |
287 return DMERR_MALLOC; | 267 return DMERR_MALLOC; |
288 | 268 |
289 // Open the file | 269 // Open the file |
290 (*pack)->file = fopen(filename, "wb"); | 270 (*pack)->file = fopen(filename, "wb"); |
291 if ((*pack)->file == NULL) | 271 if ((*pack)->file == NULL) |
300 return DMERR_OK; | 280 return DMERR_OK; |
301 } | 281 } |
302 | 282 |
303 | 283 |
304 int dmPackAddFile(DMPackFile * pack, const char *filename, | 284 int dmPackAddFile(DMPackFile * pack, const char *filename, |
305 const Uint32 flags, const BOOL compress, int level, | 285 const int level, DMPackEntry ** ppEntry) |
306 DMPackEntry ** ppEntry) | |
307 { | 286 { |
308 Uint64 startOffs, outSize; | 287 Uint64 startOffs, outSize; |
309 Uint8 *inBuffer = NULL, *outBuffer = NULL; | 288 Uint8 *inBuffer = NULL, *outBuffer = NULL; |
310 DMPackEntry entry, *node; | 289 DMPackEntry rentry, *pentry; |
311 FILE *inFile = NULL; | 290 FILE *inFile = NULL; |
312 int ret = DMERR_OK; | 291 int ret = DMERR_OK; |
313 BOOL zinit = FALSE; | 292 BOOL zinit = FALSE; |
314 z_stream zstr; | 293 z_stream zstr; |
315 | 294 |
322 return DMERR_FOPEN; | 301 return DMERR_FOPEN; |
323 | 302 |
324 // Compute starting offset | 303 // Compute starting offset |
325 outSize = 0; | 304 outSize = 0; |
326 startOffs = sizeof(DMPackFileHeader); | 305 startOffs = sizeof(DMPackFileHeader); |
327 for (node = pack->entries; node != NULL; node = node->next) | 306 for (pentry = pack->entries; pentry != NULL; pentry = pentry->next) |
328 { | 307 { |
329 startOffs += node->csize; | 308 startOffs += pentry->csize; |
330 } | 309 } |
331 | 310 |
332 // Seek to the position | 311 // Seek to the position |
333 if (fseeko(pack->file, startOffs, SEEK_SET) != 0) | 312 if (fseeko(pack->file, startOffs, SEEK_SET) != 0) |
334 return DMERR_INVALID; | 313 return DMERR_INVALID; |
344 ret = DMERR_MALLOC; | 323 ret = DMERR_MALLOC; |
345 goto out; | 324 goto out; |
346 } | 325 } |
347 | 326 |
348 // Read (and possibly compress) the data | 327 // Read (and possibly compress) the data |
349 if (compress) | 328 if (level > 0) |
350 { | 329 { |
351 int zret; | 330 int zret; |
352 | 331 |
353 // Initialize compression streams | 332 // Initialize compression streams |
354 memset(&zstr, 0, sizeof(zstr)); | 333 memset(&zstr, 0, sizeof(zstr)); |
398 } | 377 } |
399 zstr.total_in = outSize; | 378 zstr.total_in = outSize; |
400 } | 379 } |
401 | 380 |
402 // Create directory entry | 381 // Create directory entry |
403 strncpy(entry.filename, filename, DMRES_NAME_LEN); | 382 strncpy(rentry.filename, filename, DMRES_NAME_LEN); |
404 entry.filename[DMRES_NAME_LEN] = 0; | 383 rentry.filename[DMRES_NAME_LEN] = 0; |
405 entry.offset = startOffs; | 384 rentry.offset = startOffs; |
406 entry.size = zstr.total_in; | 385 rentry.size = zstr.total_in; |
407 entry.csize = outSize; | 386 rentry.csize = outSize; |
408 entry.flags = flags | (compress ? DMF_COMPRESSED : 0); | 387 rentry.flags = level > 0 ? DMF_COMPRESSED : 0; |
409 | 388 |
410 // Add directory entry | 389 // Add directory entry |
411 if ((*ppEntry = dmPackEntryCopy(&entry)) == NULL) | 390 if ((*ppEntry = dmPackEntryCopy(&rentry)) == NULL) |
412 { | 391 { |
413 ret = DMERR_MALLOC; | 392 ret = DMERR_MALLOC; |
414 goto out; | 393 goto out; |
415 } | 394 } |
416 | 395 |
428 | 407 |
429 return ret; | 408 return ret; |
430 } | 409 } |
431 | 410 |
432 | 411 |
433 /* | 412 int dmPackExtractFile(DMPackFile *pack, DMPackEntry * entry, const BOOL decompress) |
434 * EXTRACT a file from the PACK | |
435 */ | |
436 int dmPackExtractFile(DMPackFile *pack, DMPackEntry * entry, BOOL decompress) | |
437 { | 413 { |
438 z_stream zstr; | 414 z_stream zstr; |
439 FILE *outFile = NULL; | 415 FILE *outFile = NULL; |
440 Uint8 *inBuffer = NULL, *outBuffer = NULL; | 416 Uint8 *inBuffer = NULL, *outBuffer = NULL; |
441 size_t remaining; | 417 size_t remaining; |
463 ret = DMERR_MALLOC; | 439 ret = DMERR_MALLOC; |
464 goto out; | 440 goto out; |
465 } | 441 } |
466 | 442 |
467 // Read and uncompress the data, if needed | 443 // Read and uncompress the data, if needed |
468 if (decompress || (entry->flags & DMF_COMPRESSED) == 0) | 444 if (decompress && (entry->flags & DMF_COMPRESSED)) |
469 { | 445 { |
470 // Initialize compression streams | 446 // Initialize compression streams |
471 memset(&zstr, 0, sizeof(zstr)); | 447 memset(&zstr, 0, sizeof(zstr)); |
472 if (inflateInit(&zstr) != Z_OK) | 448 if (inflateInit(&zstr) != Z_OK) |
473 { | 449 { |
490 } | 466 } |
491 | 467 |
492 remaining -= zstr.avail_in; | 468 remaining -= zstr.avail_in; |
493 zstr.next_in = inBuffer; | 469 zstr.next_in = inBuffer; |
494 | 470 |
495 if (!decompress) | 471 if (zinit) |
472 { | |
473 while (zstr.avail_in > 0 && zret == Z_OK) | |
474 { | |
475 zstr.next_out = outBuffer; | |
476 zstr.avail_out = SET_TMPBUF_SIZE; | |
477 zstr.total_out = 0; | |
478 zret = inflate(&zstr, Z_FULL_FLUSH); | |
479 if (zstr.total_out > 0 && | |
480 fwrite(outBuffer, sizeof(Uint8), zstr.total_out, outFile) != zstr.total_out) | |
481 { | |
482 ret = DMERR_FWRITE; | |
483 goto out; | |
484 } | |
485 } | |
486 } | |
487 else | |
496 { | 488 { |
497 if (fwrite(inBuffer, sizeof(Uint8), zstr.avail_in, outFile) != zstr.avail_in) | 489 if (fwrite(inBuffer, sizeof(Uint8), zstr.avail_in, outFile) != zstr.avail_in) |
498 { | |
499 ret = DMERR_FWRITE; | |
500 goto out; | |
501 } | |
502 } | |
503 else | |
504 while (zstr.avail_in > 0 && zret == Z_OK) | |
505 { | |
506 zstr.next_out = outBuffer; | |
507 zstr.avail_out = SET_TMPBUF_SIZE; | |
508 zstr.total_out = 0; | |
509 zret = inflate(&zstr, Z_FULL_FLUSH); | |
510 if (zstr.total_out > 0 && | |
511 fwrite(outBuffer, sizeof(Uint8), zstr.total_out, outFile) != zstr.total_out) | |
512 { | 490 { |
513 ret = DMERR_FWRITE; | 491 ret = DMERR_FWRITE; |
514 goto out; | 492 goto out; |
515 } | 493 } |
516 } | 494 } |
641 | 619 |
642 return matched; | 620 return matched; |
643 } | 621 } |
644 | 622 |
645 | 623 |
646 BOOL dmCheckExcluded(const char *filename) | 624 BOOL dmMatchList(char **list, const size_t nlist, const char *str) |
647 { | 625 { |
648 for (int i = 0; i < nexcFilenames; i++) | 626 for (size_t i = 0; i < nlist; i++) |
649 { | 627 { |
650 if (dmStrMatch(filename, excFilenames[i])) | 628 if (dmStrMatch(str, list[i])) |
651 return TRUE; | 629 return TRUE; |
652 } | 630 } |
653 return FALSE; | 631 return FALSE; |
654 } | 632 } |
655 | 633 |
656 | 634 |
657 int main(int argc, char *argv[]) | 635 int main(int argc, char *argv[]) |
658 { | 636 { |
659 int res = 0; | 637 int res = 0; |
660 DMPackFile *pack = NULL; | 638 DMPackFile *pack = NULL; |
639 DMPackEntry *entry = NULL; | |
661 | 640 |
662 // Parse arguments | 641 // Parse arguments |
663 dmInitProg("packed", "TNSP Pack File Editor", "0.7", NULL, NULL); | 642 dmInitProg("packed", "TNSP Pack File Editor", "0.7", NULL, NULL); |
664 dmVerbosity = 0; | 643 dmVerbosity = 0; |
665 | 644 |
666 if (!dmArgsProcess(argc, argv, optList, optListN, | 645 if (!dmArgsProcess(argc, argv, optList, optListN, |
667 argHandleOpt, argHandleNonOpt, OPTH_BAILOUT)) | 646 argHandleOpt, argHandleNonOpt, OPTH_BAILOUT)) |
668 exit(1); | 647 exit(1); |
669 | 648 |
670 if (optCommand == CMD_NONE) | 649 if (optCommand == CMD_NONE || argc < 2) |
671 { | 650 { |
672 argShowHelp(); | 651 argShowHelp(); |
673 goto error; | 652 goto out; |
674 } | 653 } |
675 | 654 |
676 if (optPackFilename == NULL) | 655 if (optPackFilename == NULL) |
677 { | 656 { |
678 dmErrorMsg("No PACK file specified.\n"); | 657 dmErrorMsg("No PACK file specified.\n"); |
679 goto error; | 658 goto out; |
680 } | 659 } |
681 | 660 |
682 dmMsg(1, "Processing PACK '%s' ...\n", optPackFilename); | 661 dmMsg(1, "Processing PACK '%s' ...\n", optPackFilename); |
683 | 662 |
684 // Execute command | 663 // Execute command |
697 dmMsg(1, "Opening existing PACK\n"); | 676 dmMsg(1, "Opening existing PACK\n"); |
698 res = dmPackOpen(optPackFilename, &pack, FALSE); | 677 res = dmPackOpen(optPackFilename, &pack, FALSE); |
699 break; | 678 break; |
700 } | 679 } |
701 | 680 |
681 if (res != DMERR_OK) | |
682 { | |
683 dmErrorMsg("Could not open PACK file: %s\n", | |
684 dmErrorStr(res)); | |
685 goto out; | |
686 } | |
687 | |
702 // Add files into PACK | 688 // Add files into PACK |
703 if (res == DMERR_OK) | 689 dmMsg(1, "Adding files...\n"); |
704 { | 690 |
705 dmMsg(1, "Adding files...\n"); | 691 for (size_t i = 0; i < nsrcFilenames; i++) |
706 | 692 if (!dmMatchList(excFilenames, nexcFilenames, srcFilenames[i])) |
707 for (int i = 0; i < nsrcFilenames; i++) | 693 { |
708 if (!dmCheckExcluded(srcFilenames[i])) | 694 res = dmPackAddFile(pack, srcFilenames[i], optCompressLevel, &entry); |
709 { | 695 |
710 DMPackEntry *node = NULL; | 696 if (res != DMERR_OK) |
711 int res = dmPackAddFile(pack, srcFilenames[i], | 697 { |
712 optDefResFlags, optDoCompress, | 698 dmPrint(1, "%-32s [ERROR:%d]\n", |
713 optCompressLevel, &node); | 699 srcFilenames[i], res); |
714 | 700 } |
715 if (res != DMERR_OK) | 701 else |
716 { | 702 { |
717 dmPrint(1, "%-32s [ERROR:%d]\n", | 703 dmPrint(1, "%-32s ['%s', s=%d, c=%d, o=%" DM_PRId64 ", f=0x%04x]\n", |
718 srcFilenames[i], res); | 704 srcFilenames[i], entry->filename, |
719 } | 705 entry->size, entry->csize, entry->offset, |
720 else | 706 entry->flags); |
721 { | 707 } |
722 dmPrint(1, "%-32s ['%s', s=%d, c=%d, o=%" DM_PRId64 ", f=0x%04x]\n", | 708 } |
723 srcFilenames[i], node->filename, | 709 |
724 node->size, node->csize, node->offset, node->flags); | 710 dmMsg(2, "w=%d\n", dmPackWrite(pack)); |
725 } | |
726 } | |
727 | |
728 dmMsg(2, "w=%d\n", dmPackWrite(pack)); | |
729 dmMsg(2, "c=%d\n", dmPackClose(pack)); | |
730 } | |
731 else | |
732 { | |
733 dmErrorMsg("Could not open packfile, error #%d: %s\n", res, | |
734 dmErrorStr(res)); | |
735 } | |
736 break; | 711 break; |
737 | 712 |
738 case CMD_LIST: | 713 case CMD_LIST: |
739 // List files in PACK | 714 // List files in PACK |
740 res = dmPackOpen(optPackFilename, &pack, TRUE); | 715 if ((res = dmPackOpen(optPackFilename, &pack, TRUE)) != DMERR_OK) |
741 if (res == DMERR_OK) | 716 { |
742 { | 717 dmErrorMsg("Could not open PACK file: %s\n", |
743 DMPackEntry *node; | 718 dmErrorStr(res)); |
744 int i; | 719 goto out; |
745 for (i = 0, node = pack->entries; node; i++) | 720 } |
746 node = node->next; | 721 else |
747 | 722 { |
748 dmMsg(1, "%d files total\n", i); | 723 size_t ntotal = 0, nshown = 0, |
749 | 724 totalSize = 0, totalCSize = 0; |
750 dmPrint(0, "%-32s | %8s | %8s | %8s | %s\n", | 725 |
751 "Name", "Size", "CSize", "Offset", "ResFlags"); | 726 // Print the list header |
752 | 727 int hlen = printf( |
753 for (node = pack->entries; node != NULL; node = node->next) | 728 "%-32s | %10s | %10s | %10s | %s\n", |
729 "Name", "Size", "CSize", "Offset", "Flags"); | |
730 | |
731 for (int n = 0; n < hlen; n++) | |
732 fputc('-', stdout); | |
733 | |
734 fputs("\n", stdout); | |
735 | |
736 // Print all the matching entries | |
737 for (entry = pack->entries; entry != NULL; entry = entry->next) | |
754 { | 738 { |
755 BOOL match; | 739 BOOL match; |
756 | 740 |
757 // Check for matches in specified filenames/patterns | |
758 if (nsrcFilenames > 0) | 741 if (nsrcFilenames > 0) |
742 // Check for matches in specified filenames/patterns | |
743 match = dmMatchList(srcFilenames, nsrcFilenames, entry->filename); | |
744 else | |
745 // No filenames specified, everything shown | |
746 match = TRUE; | |
747 | |
748 if (match && !dmMatchList(excFilenames, nexcFilenames, entry->filename)) | |
759 { | 749 { |
760 match = FALSE; | 750 printf("%-32s | %10d | %10d | %010" DM_PRIx64 " | %04x\n", |
761 for (int i = 0; i < nsrcFilenames && !match; i++) | 751 entry->filename, entry->size, entry->csize, |
762 match = dmStrMatch(node->filename, srcFilenames[i]); | 752 entry->offset, entry->flags); |
753 | |
754 nshown++; | |
755 totalSize += entry->size; | |
756 totalCSize += entry->csize; | |
763 } | 757 } |
764 else | 758 |
765 // No filenames specified, everything shown | 759 ntotal++; |
766 match = TRUE; | 760 } |
767 | 761 |
768 if (match) | 762 for (int n = 0; n < hlen; n++) |
769 { | 763 fputc('-', stdout); |
770 dmPrint(0, "%-32s | %8d | %8d | %08" DM_PRIx64 " | %04x\n", | 764 |
771 node->filename, node->size, node->csize, | 765 printf( |
772 node->offset, node->flags); | 766 "\n" |
773 } | 767 "%-32s | %10" DM_PRIu_SIZE_T " | %10" DM_PRIu_SIZE_T " |\n" |
774 } | 768 "Listed %" DM_PRIu_SIZE_T " of %" DM_PRIu_SIZE_T " files total.\n", |
775 | 769 "Totals", |
776 dmMsg(2, "c=%d\n", dmPackClose(pack)); | 770 totalSize, totalCSize, |
777 } | 771 nshown, ntotal); |
778 else | 772 } |
779 dmErrorMsg("Could not open packfile, error #%d: %s\n", res, | |
780 dmErrorStr(res)); | |
781 break; | 773 break; |
782 | 774 |
783 case CMD_EXTRACT: | 775 case CMD_EXTRACT: |
784 // Extract files from PACK | 776 // Extract files from PACK |
785 res = dmPackOpen(optPackFilename, &pack, TRUE); | 777 if ((res = dmPackOpen(optPackFilename, &pack, TRUE)) != DMERR_OK) |
786 if (res == DMERR_OK) | 778 { |
787 { | 779 dmErrorMsg("Could not open PACK file: %s\n", |
788 DMPackEntry *node; | 780 dmErrorStr(res)); |
789 FILE *resFile = fopen(DMRES_RES_FILE, "w"); | 781 goto out; |
790 if (resFile == NULL) | 782 } |
791 { | 783 |
792 int err = dmGetErrno(); | 784 for (entry = pack->entries; entry != NULL; entry = entry->next) |
793 dmErrorMsg("Could not create resource output file '%s' #%d: %s\n", | 785 { |
794 DMRES_RES_FILE, err, dmErrorStr(err)); | 786 BOOL match; |
795 } | 787 |
796 | 788 // Check for matches |
797 for (node = pack->entries; node != NULL; node = node->next) | 789 if (nsrcFilenames > 0) |
798 { | 790 { |
799 BOOL match; | 791 match = !dmMatchList(excFilenames, nexcFilenames, entry->filename) && |
800 | 792 dmMatchList(srcFilenames, nsrcFilenames, entry->filename); |
801 // Check for matches | 793 } |
802 if (nsrcFilenames > 0) | 794 else |
803 { | 795 { |
804 match = FALSE; | 796 match = !dmMatchList(excFilenames, nexcFilenames, entry->filename); |
805 for (int i = 0; i < nsrcFilenames && !match; i++) | 797 } |
806 { | 798 |
807 if (dmStrMatch(node->filename, srcFilenames[i]) && | 799 if (match && (entry->privFlags & PACK_EXTRACTED) == 0) |
808 !dmCheckExcluded(node->filename)) | 800 { |
809 match = TRUE; | 801 // Print one entry |
810 } | 802 dmPrint(0, "Extracting: %-32s [siz=%d, cmp=%d, offs=0x%08" DM_PRIx64 ", flags=0x%04x]\n", |
811 } | 803 entry->filename, entry->size, entry->csize, |
812 else | 804 entry->offset, entry->flags); |
813 { | 805 |
814 match = !dmCheckExcluded(node->filename); | 806 if ((res = dmPackExtractFile(pack, entry, optCompressLevel > 0)) == DMERR_OK) |
815 } | 807 entry->privFlags |= PACK_EXTRACTED; |
816 | 808 } |
817 if (match && (node->privFlags & PACK_EXTRACTED) == 0) | 809 } |
818 { | |
819 // Mark as done | |
820 node->privFlags |= PACK_EXTRACTED; | |
821 | |
822 // Print one entry | |
823 dmPrint(0, "Extracting: %-32s [siz=%d, cmp=%d, offs=0x%08" DM_PRIx64 ", flags=0x%04x]\n", | |
824 node->filename, node->size, node->csize, | |
825 node->offset, node->flags); | |
826 | |
827 dmPackExtractFile(pack, node, optDoCompress); | |
828 } | |
829 } | |
830 | |
831 dmMsg(2, "c=%d\n", dmPackClose(pack)); | |
832 | |
833 if (resFile != NULL) | |
834 fclose(resFile); | |
835 } | |
836 else | |
837 dmErrorMsg("Could not open packfile, error #%d: %s\n", res, | |
838 dmErrorStr(res)); | |
839 break; | 810 break; |
840 } | 811 } |
841 | 812 |
842 error: | 813 out: |
814 dmPackClose(pack); | |
815 | |
843 return 0; | 816 return 0; |
844 } | 817 } |