#define KONPACK_WRITER #include "konpack.h" #include #include #include static void usage(void) { fprintf(stderr, "usage: konpack -c out.kpk [-k keyfile] [-b basedir] [-l listfile] [file ...]\n" " konpack -t pack.kpk [-k keyfile]\n" " konpack -x pack.kpk name [-k keyfile]\n" "keyfile is 32 raw bytes, listfile has one path per line\n"); } static int readKey(const char *path, uint8_t *key) { FILE *f = fopen(path, "rb"); size_t got; uint8_t extra; if (!f) { fprintf(stderr, "konpack: cannot open key file %s\n", path); return -1; } got = fread(key, 1, KON_PACK_KEY_SIZE, f); if (got != KON_PACK_KEY_SIZE || fread(&extra, 1, 1, f) != 0) { fprintf(stderr, "konpack: key file must be exactly %d bytes\n", KON_PACK_KEY_SIZE); fclose(f); return -1; } fclose(f); return 0; } static int readList(const char *path, char ***files, int *count) { FILE *f = fopen(path, "r"); char line[4096]; char **list = NULL; int n = 0, capacity = 0; if (!f) { fprintf(stderr, "konpack: cannot open list file %s\n", path); return -1; } while (fgets(line, sizeof(line), f)) { size_t length = strlen(line); while (length > 0 && (line[length - 1] == '\n' || line[length - 1] == '\r')) line[--length] = '\0'; if (length == 0) continue; if (n == capacity) { char **grown; capacity = capacity ? capacity * 2 : 64; grown = realloc(list, (size_t)capacity * sizeof(char *)); if (!grown) { fclose(f); return -1; } list = grown; } list[n] = malloc(length + 1); if (!list[n]) { fclose(f); return -1; } memcpy(list[n], line, length + 1); n++; } fclose(f); *files = list; *count = n; return 0; } int main(int argc, char **argv) { uint8_t key[KON_PACK_KEY_SIZE]; const uint8_t *keyPointer = NULL; const char *baseDir = NULL, *listFile = NULL, *pack = NULL, *name = NULL; char mode = 0; char **listed = NULL; int listedCount = 0; const char **files; int fileCount = 0; int result = 1; files = malloc((size_t)(argc > 0 ? argc : 1) * sizeof(char *)); if (!files) return 1; for (int i = 1; i < argc; i++) { if (argv[i][0] == '-' && argv[i][1] != '\0' && argv[i][2] == '\0') { char option = argv[i][1]; if (option == 'c' || option == 't' || option == 'x') { if (mode || i + 1 >= argc) { usage(); goto done; } mode = option; pack = argv[++i]; } else if (option == 'k' || option == 'b' || option == 'l') { if (i + 1 >= argc) { usage(); goto done; } i++; if (option == 'k') { if (readKey(argv[i], key) != 0) goto done; keyPointer = key; } else if (option == 'b') { baseDir = argv[i]; } else { listFile = argv[i]; } } else { usage(); goto done; } } else if (mode == 'x' && !name) { name = argv[i]; } else { files[fileCount++] = argv[i]; } } if (mode == 'c') { if (listFile) { if (readList(listFile, &listed, &listedCount) != 0) goto done; for (int i = 0; i < listedCount; i++) files[fileCount++] = listed[i]; } if (kon_packWrite(pack, keyPointer, baseDir, files, fileCount) != 0) { fprintf(stderr, "konpack: %s\n", kon_packError()); goto done; } printf("%s: %d files%s\n", pack, fileCount, keyPointer ? ", encrypted" : ""); result = 0; } else if (mode == 't' || mode == 'x') { kon_pack_t *p = kon_packOpen(pack, keyPointer); if (!p) { fprintf(stderr, "konpack: %s\n", kon_packError()); goto done; } if (mode == 't') { for (int i = 0; i < kon_packCount(p); i++) printf("%10u %s\n", kon_packSize(p, i), kon_packName(p, i)); result = 0; } else if (name) { int index = kon_packFind(p, name); size_t size; uint8_t *data = index >= 0 ? kon_packRead(p, index, &size) : NULL; if (!data) { fprintf(stderr, "konpack: %s\n", index < 0 ? "no such file in the pack" : kon_packError()); } else { fwrite(data, 1, size, stdout); free(data); result = 0; } } else { usage(); } kon_packClose(p); } else { usage(); } done: for (int i = 0; i < listedCount; i++) free(listed[i]); free(listed); free(files); return result; }