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 }