# HG changeset patch # User Matti Hamalainen # Date 1588012635 -10800 # Node ID c7a0913e1032ffe56a06b2c0d8f561a1e66afd72 # Parent c1cae47cd4102aa2c53bcf49361011bdee685637 Various cleanups, integrate some changes/improvements from opendat project to packed. diff -r c1cae47cd410 -r c7a0913e1032 tools/packed.c --- a/tools/packed.c Mon Apr 27 21:33:29 2020 +0300 +++ b/tools/packed.c Mon Apr 27 21:37:15 2020 +0300 @@ -29,15 +29,14 @@ PACK_EXTRACTED = 0x0001, }; -int nsrcFilenames = 0, nexcFilenames = 0; + +size_t nsrcFilenames = 0, nexcFilenames = 0; char * srcFilenames[SET_MAX_FILES]; char * excFilenames[SET_MAX_FILES]; char * optPackFilename = NULL; -BOOL optDoCompress = TRUE; int optCompressLevel = Z_BEST_COMPRESSION; int optCommand = CMD_NONE; -int optDefResFlags = 0; static const DMOptArg cmdList[] = @@ -57,9 +56,7 @@ { 1, 0, "license" , "Print out this program's license agreement", OPT_NONE }, { 2, 'v', "verbose" , "Be more verbose", OPT_NONE }, - { 3, 'n', "nocompress" , "No compression / decompression", OPT_NONE }, - { 4, 'C', "level" , "Set zlib compression level 1-9", OPT_ARGREQ }, - { 5, 'f', "resflags" , "Set default resource flags (-f 0xff)", OPT_ARGREQ }, + { 4, 'C', "level" , "Set zlib compression level 0-9", OPT_ARGREQ }, { 6, 'x', "exclude" , "Exclude name/glob pattern", OPT_ARGREQ }, }; @@ -116,31 +113,15 @@ dmVerbosity++; break; - case 3: - optDoCompress = FALSE; - break; - case 4: optCompressLevel = atoi(optArg); - if (optCompressLevel < 1 || optCompressLevel > 9) + if (optCompressLevel < 0 || optCompressLevel > 9) { - dmErrorMsg("Invalid compression level argument '%s', must be 1 .. 9.\n", optArg); + dmErrorMsg("Invalid compression level argument '%s', must be 0 .. 9.\n", optArg); return FALSE; } break; - case 5: - { - unsigned int tmpUI; - if (!dmGetIntVal(optArg, &tmpUI, NULL)) - { - dmErrorMsg("Invalid flags value '%s'.\n", optArg); - return FALSE; - } - optDefResFlags = tmpUI; - } - break; - case 6: if (nexcFilenames < SET_MAX_FILES) { @@ -206,25 +187,25 @@ DMPackEntry *dmPackEntryCopy(const DMPackEntry *src) { - DMPackEntry *node = dmPackEntryNew(); - if (node == NULL) + DMPackEntry *entry = dmPackEntryNew(); + if (entry == NULL) return NULL; - strncpy(node->filename, src->filename, DMRES_NAME_LEN); - node->filename[DMRES_NAME_LEN] = 0; + strncpy(entry->filename, src->filename, DMRES_NAME_LEN); + entry->filename[DMRES_NAME_LEN] = 0; - node->size = src->size; - node->offset = src->offset; - node->csize = src->csize; - node->flags = src->flags; + entry->size = src->size; + entry->offset = src->offset; + entry->csize = src->csize; + entry->flags = src->flags; - return node; + return entry; } int dmPackWrite(DMPackFile * pack) { - DMPackEntry *node; + DMPackEntry *entry; DMPackFileHeader hdr; if (pack == NULL) @@ -241,10 +222,10 @@ sizeof(hdr.ident) + sizeof(hdr.version) + sizeof(hdr.dirEntries) + sizeof(hdr.dirOffset); - for (node = pack->entries; node != NULL; node = node->next) + for (entry = pack->entries; entry != NULL; entry = entry->next) { hdr.dirEntries++; - hdr.dirOffset += node->csize; + hdr.dirOffset += entry->csize; } dmMsg(1, "%d entries in PACK, dir at offset 0x%08" DM_PRIx64 ".\n", @@ -264,14 +245,14 @@ if (fseeko(pack->file, hdr.dirOffset, SEEK_SET) != 0) return DMERR_FSEEK; - for (node = pack->entries; node != NULL; node = node->next) + for (entry = pack->entries; entry != NULL; entry = entry->next) { // Write one entry - if (!dm_fwrite_str(pack->file, node->filename, DMRES_NAME_LEN) || - !dm_fwrite_le64(pack->file, node->offset) || - !dm_fwrite_le32(pack->file, node->csize) || - !dm_fwrite_le32(pack->file, node->size) || - !dm_fwrite_le32(pack->file, node->flags)) + if (!dm_fwrite_str(pack->file, entry->filename, DMRES_NAME_LEN) || + !dm_fwrite_le64(pack->file, entry->offset) || + !dm_fwrite_le32(pack->file, entry->csize) || + !dm_fwrite_le32(pack->file, entry->size) || + !dm_fwrite_le32(pack->file, entry->flags)) return DMERR_FWRITE; } @@ -282,8 +263,7 @@ int dmPackCreate(const char *filename, DMPackFile ** pack) { // Allocate packfile-structure - *pack = (DMPackFile *) dmMalloc0(sizeof(DMPackFile)); - if (*pack == NULL) + if ((*pack = (DMPackFile *) dmMalloc0(sizeof(DMPackFile))) == NULL) return DMERR_MALLOC; // Open the file @@ -302,12 +282,11 @@ int dmPackAddFile(DMPackFile * pack, const char *filename, - const Uint32 flags, const BOOL compress, int level, - DMPackEntry ** ppEntry) + const int level, DMPackEntry ** ppEntry) { Uint64 startOffs, outSize; Uint8 *inBuffer = NULL, *outBuffer = NULL; - DMPackEntry entry, *node; + DMPackEntry rentry, *pentry; FILE *inFile = NULL; int ret = DMERR_OK; BOOL zinit = FALSE; @@ -324,9 +303,9 @@ // Compute starting offset outSize = 0; startOffs = sizeof(DMPackFileHeader); - for (node = pack->entries; node != NULL; node = node->next) + for (pentry = pack->entries; pentry != NULL; pentry = pentry->next) { - startOffs += node->csize; + startOffs += pentry->csize; } // Seek to the position @@ -346,7 +325,7 @@ } // Read (and possibly compress) the data - if (compress) + if (level > 0) { int zret; @@ -400,15 +379,15 @@ } // Create directory entry - strncpy(entry.filename, filename, DMRES_NAME_LEN); - entry.filename[DMRES_NAME_LEN] = 0; - entry.offset = startOffs; - entry.size = zstr.total_in; - entry.csize = outSize; - entry.flags = flags | (compress ? DMF_COMPRESSED : 0); + strncpy(rentry.filename, filename, DMRES_NAME_LEN); + rentry.filename[DMRES_NAME_LEN] = 0; + rentry.offset = startOffs; + rentry.size = zstr.total_in; + rentry.csize = outSize; + rentry.flags = level > 0 ? DMF_COMPRESSED : 0; // Add directory entry - if ((*ppEntry = dmPackEntryCopy(&entry)) == NULL) + if ((*ppEntry = dmPackEntryCopy(&rentry)) == NULL) { ret = DMERR_MALLOC; goto out; @@ -430,10 +409,7 @@ } -/* - * EXTRACT a file from the PACK - */ -int dmPackExtractFile(DMPackFile *pack, DMPackEntry * entry, BOOL decompress) +int dmPackExtractFile(DMPackFile *pack, DMPackEntry * entry, const BOOL decompress) { z_stream zstr; FILE *outFile = NULL; @@ -465,7 +441,7 @@ } // Read and uncompress the data, if needed - if (decompress || (entry->flags & DMF_COMPRESSED) == 0) + if (decompress && (entry->flags & DMF_COMPRESSED)) { // Initialize compression streams memset(&zstr, 0, sizeof(zstr)); @@ -492,23 +468,25 @@ remaining -= zstr.avail_in; zstr.next_in = inBuffer; - if (!decompress) + if (zinit) { - if (fwrite(inBuffer, sizeof(Uint8), zstr.avail_in, outFile) != zstr.avail_in) + while (zstr.avail_in > 0 && zret == Z_OK) { - ret = DMERR_FWRITE; - goto out; + zstr.next_out = outBuffer; + zstr.avail_out = SET_TMPBUF_SIZE; + zstr.total_out = 0; + zret = inflate(&zstr, Z_FULL_FLUSH); + if (zstr.total_out > 0 && + fwrite(outBuffer, sizeof(Uint8), zstr.total_out, outFile) != zstr.total_out) + { + ret = DMERR_FWRITE; + goto out; + } } } else - while (zstr.avail_in > 0 && zret == Z_OK) { - zstr.next_out = outBuffer; - zstr.avail_out = SET_TMPBUF_SIZE; - zstr.total_out = 0; - zret = inflate(&zstr, Z_FULL_FLUSH); - if (zstr.total_out > 0 && - fwrite(outBuffer, sizeof(Uint8), zstr.total_out, outFile) != zstr.total_out) + if (fwrite(inBuffer, sizeof(Uint8), zstr.avail_in, outFile) != zstr.avail_in) { ret = DMERR_FWRITE; goto out; @@ -643,11 +621,11 @@ } -BOOL dmCheckExcluded(const char *filename) +BOOL dmMatchList(char **list, const size_t nlist, const char *str) { - for (int i = 0; i < nexcFilenames; i++) + for (size_t i = 0; i < nlist; i++) { - if (dmStrMatch(filename, excFilenames[i])) + if (dmStrMatch(str, list[i])) return TRUE; } return FALSE; @@ -658,6 +636,7 @@ { int res = 0; DMPackFile *pack = NULL; + DMPackEntry *entry = NULL; // Parse arguments dmInitProg("packed", "TNSP Pack File Editor", "0.7", NULL, NULL); @@ -667,16 +646,16 @@ argHandleOpt, argHandleNonOpt, OPTH_BAILOUT)) exit(1); - if (optCommand == CMD_NONE) + if (optCommand == CMD_NONE || argc < 2) { argShowHelp(); - goto error; + goto out; } if (optPackFilename == NULL) { dmErrorMsg("No PACK file specified.\n"); - goto error; + goto out; } dmMsg(1, "Processing PACK '%s' ...\n", optPackFilename); @@ -699,146 +678,140 @@ break; } - // Add files into PACK - if (res == DMERR_OK) + if (res != DMERR_OK) { - dmMsg(1, "Adding files...\n"); + dmErrorMsg("Could not open PACK file: %s\n", + dmErrorStr(res)); + goto out; + } - for (int i = 0; i < nsrcFilenames; i++) - if (!dmCheckExcluded(srcFilenames[i])) - { - DMPackEntry *node = NULL; - int res = dmPackAddFile(pack, srcFilenames[i], - optDefResFlags, optDoCompress, - optCompressLevel, &node); + // Add files into PACK + dmMsg(1, "Adding files...\n"); + + for (size_t i = 0; i < nsrcFilenames; i++) + if (!dmMatchList(excFilenames, nexcFilenames, srcFilenames[i])) + { + res = dmPackAddFile(pack, srcFilenames[i], optCompressLevel, &entry); - if (res != DMERR_OK) - { - dmPrint(1, "%-32s [ERROR:%d]\n", - srcFilenames[i], res); - } - else - { - dmPrint(1, "%-32s ['%s', s=%d, c=%d, o=%" DM_PRId64 ", f=0x%04x]\n", - srcFilenames[i], node->filename, - node->size, node->csize, node->offset, node->flags); - } + if (res != DMERR_OK) + { + dmPrint(1, "%-32s [ERROR:%d]\n", + srcFilenames[i], res); } - - dmMsg(2, "w=%d\n", dmPackWrite(pack)); - dmMsg(2, "c=%d\n", dmPackClose(pack)); + else + { + dmPrint(1, "%-32s ['%s', s=%d, c=%d, o=%" DM_PRId64 ", f=0x%04x]\n", + srcFilenames[i], entry->filename, + entry->size, entry->csize, entry->offset, + entry->flags); + } } - else - { - dmErrorMsg("Could not open packfile, error #%d: %s\n", res, - dmErrorStr(res)); - } + + dmMsg(2, "w=%d\n", dmPackWrite(pack)); break; case CMD_LIST: // List files in PACK - res = dmPackOpen(optPackFilename, &pack, TRUE); - if (res == DMERR_OK) + if ((res = dmPackOpen(optPackFilename, &pack, TRUE)) != DMERR_OK) + { + dmErrorMsg("Could not open PACK file: %s\n", + dmErrorStr(res)); + goto out; + } + else { - DMPackEntry *node; - int i; - for (i = 0, node = pack->entries; node; i++) - node = node->next; + size_t ntotal = 0, nshown = 0, + totalSize = 0, totalCSize = 0; + + // Print the list header + int hlen = printf( + "%-32s | %10s | %10s | %10s | %s\n", + "Name", "Size", "CSize", "Offset", "Flags"); - dmMsg(1, "%d files total\n", i); + for (int n = 0; n < hlen; n++) + fputc('-', stdout); - dmPrint(0, "%-32s | %8s | %8s | %8s | %s\n", - "Name", "Size", "CSize", "Offset", "ResFlags"); + fputs("\n", stdout); - for (node = pack->entries; node != NULL; node = node->next) + // Print all the matching entries + for (entry = pack->entries; entry != NULL; entry = entry->next) { BOOL match; - // Check for matches in specified filenames/patterns if (nsrcFilenames > 0) - { - match = FALSE; - for (int i = 0; i < nsrcFilenames && !match; i++) - match = dmStrMatch(node->filename, srcFilenames[i]); - } + // Check for matches in specified filenames/patterns + match = dmMatchList(srcFilenames, nsrcFilenames, entry->filename); else - // No filenames specified, everything shown + // No filenames specified, everything shown match = TRUE; - if (match) + if (match && !dmMatchList(excFilenames, nexcFilenames, entry->filename)) { - dmPrint(0, "%-32s | %8d | %8d | %08" DM_PRIx64 " | %04x\n", - node->filename, node->size, node->csize, - node->offset, node->flags); + printf("%-32s | %10d | %10d | %010" DM_PRIx64 " | %04x\n", + entry->filename, entry->size, entry->csize, + entry->offset, entry->flags); + + nshown++; + totalSize += entry->size; + totalCSize += entry->csize; } + + ntotal++; } - dmMsg(2, "c=%d\n", dmPackClose(pack)); + for (int n = 0; n < hlen; n++) + fputc('-', stdout); + + printf( + "\n" + "%-32s | %10" DM_PRIu_SIZE_T " | %10" DM_PRIu_SIZE_T " |\n" + "Listed %" DM_PRIu_SIZE_T " of %" DM_PRIu_SIZE_T " files total.\n", + "Totals", + totalSize, totalCSize, + nshown, ntotal); } - else - dmErrorMsg("Could not open packfile, error #%d: %s\n", res, - dmErrorStr(res)); break; case CMD_EXTRACT: // Extract files from PACK - res = dmPackOpen(optPackFilename, &pack, TRUE); - if (res == DMERR_OK) + if ((res = dmPackOpen(optPackFilename, &pack, TRUE)) != DMERR_OK) + { + dmErrorMsg("Could not open PACK file: %s\n", + dmErrorStr(res)); + goto out; + } + + for (entry = pack->entries; entry != NULL; entry = entry->next) { - DMPackEntry *node; - FILE *resFile = fopen(DMRES_RES_FILE, "w"); - if (resFile == NULL) + BOOL match; + + // Check for matches + if (nsrcFilenames > 0) { - int err = dmGetErrno(); - dmErrorMsg("Could not create resource output file '%s' #%d: %s\n", - DMRES_RES_FILE, err, dmErrorStr(err)); + match = !dmMatchList(excFilenames, nexcFilenames, entry->filename) && + dmMatchList(srcFilenames, nsrcFilenames, entry->filename); + } + else + { + match = !dmMatchList(excFilenames, nexcFilenames, entry->filename); } - for (node = pack->entries; node != NULL; node = node->next) + if (match && (entry->privFlags & PACK_EXTRACTED) == 0) { - BOOL match; - - // Check for matches - if (nsrcFilenames > 0) - { - match = FALSE; - for (int i = 0; i < nsrcFilenames && !match; i++) - { - if (dmStrMatch(node->filename, srcFilenames[i]) && - !dmCheckExcluded(node->filename)) - match = TRUE; - } - } - else - { - match = !dmCheckExcluded(node->filename); - } + // Print one entry + dmPrint(0, "Extracting: %-32s [siz=%d, cmp=%d, offs=0x%08" DM_PRIx64 ", flags=0x%04x]\n", + entry->filename, entry->size, entry->csize, + entry->offset, entry->flags); - if (match && (node->privFlags & PACK_EXTRACTED) == 0) - { - // Mark as done - node->privFlags |= PACK_EXTRACTED; - - // Print one entry - dmPrint(0, "Extracting: %-32s [siz=%d, cmp=%d, offs=0x%08" DM_PRIx64 ", flags=0x%04x]\n", - node->filename, node->size, node->csize, - node->offset, node->flags); - - dmPackExtractFile(pack, node, optDoCompress); - } + if ((res = dmPackExtractFile(pack, entry, optCompressLevel > 0)) == DMERR_OK) + entry->privFlags |= PACK_EXTRACTED; } - - dmMsg(2, "c=%d\n", dmPackClose(pack)); - - if (resFile != NULL) - fclose(resFile); } - else - dmErrorMsg("Could not open packfile, error #%d: %s\n", res, - dmErrorStr(res)); break; } -error: +out: + dmPackClose(pack); + return 0; }