From 2364f53649c695389e459f51a0fcc06f7538d4f5 Mon Sep 17 00:00:00 2001 From: Stephen Seo Date: Wed, 17 Jul 2024 13:30:05 +0900 Subject: [PATCH] Impl. "-t" command (printing archive info) TODO: Write symbolic links into archive when creating. Use De/compressor cmds when creating archive. Extracting archive. --- src/archiver.c | 184 +++++++++++++++++++++++++++++++++++++++++++++++++ src/archiver.h | 6 +- src/main.c | 24 +++++-- 3 files changed, 208 insertions(+), 6 deletions(-) diff --git a/src/archiver.c b/src/archiver.c index b232b2c..243562b 100644 --- a/src/archiver.c +++ b/src/archiver.c @@ -36,6 +36,13 @@ void free_FILE_helper(FILE **fd) { } } +void free_malloced_memory(void **data) { + if (data && *data) { + free(*data); + *data = NULL; + } +} + void free_internal_to_write(void *data) { SDArchiverInternalToWrite *to_write = data; free(to_write->buf); @@ -275,3 +282,180 @@ int simple_archiver_write_all(FILE *out_f, SDArchiverState *state, fprintf(stderr, "End archiving.\n"); return SDAS_SUCCESS; } + +int simple_archiver_print_archive_info(FILE *in_f) { + unsigned char buf[1024]; + memset(buf, 0, 1024); + uint16_t u16; + uint32_t u32; + uint64_t u64; + + if (fread(buf, 1, 18, in_f) != 18) { + return SDAS_INVALID_FILE; + } else if (memcmp(buf, "SIMPLE_ARCHIVE_VER", 18) != 0) { + return SDAS_INVALID_FILE; + } else if (fread(buf, 1, 2, in_f) != 2) { + return SDAS_INVALID_FILE; + } else if (buf[0] != 0 || buf[1] != 0) { + // Version is not zero. + return SDAS_INVALID_FILE; + } else if (fread(buf, 1, 4, in_f) != 4) { + return SDAS_INVALID_FILE; + } + + if ((buf[0] & 1) != 0) { + fprintf(stderr, "De/compressor flag is set.\n"); + + // Read compressor data. + if (fread(&u16, 2, 1, in_f) != 1) { + return SDAS_INVALID_FILE; + } + simple_archiver_helper_16_bit_be(&u16); + fprintf(stderr, "Compressor size is %u\n", u16); + if (u16 < 1024) { + if (fread(buf, 1, u16 + 1, in_f) != (size_t)u16 + 1) { + return SDAS_INVALID_FILE; + } + buf[1023] = 0; + fprintf(stderr, "Compressor cmd: %s\n", buf); + } else { + __attribute__((cleanup(free_malloced_memory))) void *heap_buf = + malloc(u16 + 1); + unsigned char *uc_heap_buf = heap_buf; + if (fread(uc_heap_buf, 1, u16 + 1, in_f) != (size_t)u16 + 1) { + return SDAS_INVALID_FILE; + } + uc_heap_buf[u16 - 1] = 0; + fprintf(stderr, "Compressor cmd: %s\n", uc_heap_buf); + } + + // Read decompressor data. + if (fread(&u16, 2, 1, in_f) != 1) { + return SDAS_INVALID_FILE; + } + simple_archiver_helper_16_bit_be(&u16); + fprintf(stderr, "Decompressor size is %u\n", u16); + if (u16 < 1024) { + if (fread(buf, 1, u16 + 1, in_f) != (size_t)u16 + 1) { + return SDAS_INVALID_FILE; + } + buf[1023] = 0; + fprintf(stderr, "Decompressor cmd: %s\n", buf); + } else { + __attribute__((cleanup(free_malloced_memory))) void *heap_buf = + malloc(u16 + 1); + unsigned char *uc_heap_buf = heap_buf; + if (fread(uc_heap_buf, 1, u16 + 1, in_f) != (size_t)u16 + 1) { + return SDAS_INVALID_FILE; + } + uc_heap_buf[u16 - 1] = 0; + fprintf(stderr, "Decompressor cmd: %s\n", uc_heap_buf); + } + } else { + fprintf(stderr, "De/compressor flag is NOT set.\n"); + } + + if (fread(&u32, 1, 4, in_f) != 4) { + return SDAS_INVALID_FILE; + } + simple_archiver_helper_32_bit_be(&u32); + fprintf(stderr, "File count is %u\n", u32); + + uint32_t size = u32; + for (uint32_t idx = 0; idx < size; ++idx) { + fprintf(stderr, "File %10u of %10u.\n", idx + 1, size); + if (feof(in_f) || ferror(in_f)) { + return SDAS_INVALID_FILE; + } else if (fread(&u16, 2, 1, in_f) != 1) { + return SDAS_INVALID_FILE; + } + simple_archiver_helper_16_bit_be(&u16); + if (u16 < 1024) { + if (fread(buf, 1, u16 + 1, in_f) != (size_t)u16 + 1) { + return SDAS_INVALID_FILE; + } + buf[1023] = 0; + fprintf(stderr, " Filename: %s\n", buf); + } else { + __attribute__((cleanup(free_malloced_memory))) void *heap_buf = + malloc(u16 + 1); + unsigned char *uc_heap_buf = heap_buf; + if (fread(uc_heap_buf, 1, u16 + 1, in_f) != (size_t)u16 + 1) { + return SDAS_INVALID_FILE; + } + uc_heap_buf[u16 - 1] = 0; + fprintf(stderr, " Filename: %s\n", uc_heap_buf); + } + + if (fread(buf, 1, 4, in_f) != 4) { + return SDAS_INVALID_FILE; + } + + if ((buf[0] & 1) == 0) { + // Not a sybolic link. + if (fread(&u64, 8, 1, in_f) != 1) { + return SDAS_INVALID_FILE; + } + simple_archiver_helper_64_bit_be(&u64); + fprintf(stderr, " File size: %lu\n", u64); + while (u64 > 0) { + if (u64 > 1024) { + if (fread(buf, 1, 1024, in_f) != 1024) { + return SDAS_INVALID_FILE; + } + u64 -= 1024; + } else { + if (fread(buf, 1, u64, in_f) != u64) { + return SDAS_INVALID_FILE; + } + u64 = 0; + } + } + } else { + // Is a symbolic link. + if (fread(&u16, 2, 1, in_f) != 1) { + return SDAS_INVALID_FILE; + } + simple_archiver_helper_16_bit_be(&u16); + if (u16 < 1024) { + if (fread(buf, 1, u16 + 1, in_f) != (size_t)u16 + 1) { + return SDAS_INVALID_FILE; + } + buf[1023] = 0; + fprintf(stderr, " Link absolute path: %s\n", buf); + } else { + __attribute__((cleanup(free_malloced_memory))) void *heap_buf = + malloc(u16 + 1); + unsigned char *uc_heap_buf = heap_buf; + if (fread(uc_heap_buf, 1, u16 + 1, in_f) != (size_t)u16 + 1) { + return SDAS_INVALID_FILE; + } + uc_heap_buf[u16 - 1] = 0; + fprintf(stderr, " Link absolute path: %s\n", uc_heap_buf); + } + + if (fread(&u16, 2, 1, in_f) != 1) { + return SDAS_INVALID_FILE; + } + simple_archiver_helper_16_bit_be(&u16); + if (u16 < 1024) { + if (fread(buf, 1, u16 + 1, in_f) != (size_t)u16 + 1) { + return SDAS_INVALID_FILE; + } + buf[1023] = 0; + fprintf(stderr, " Link relative path: %s\n", buf); + } else { + __attribute__((cleanup(free_malloced_memory))) void *heap_buf = + malloc(u16 + 1); + unsigned char *uc_heap_buf = heap_buf; + if (fread(uc_heap_buf, 1, u16 + 1, in_f) != (size_t)u16 + 1) { + return SDAS_INVALID_FILE; + } + uc_heap_buf[u16 - 1] = 0; + fprintf(stderr, " Link relative path: %s\n", uc_heap_buf); + } + } + } + + return 0; +} diff --git a/src/archiver.h b/src/archiver.h index dcbb852..91ff4e7 100644 --- a/src/archiver.h +++ b/src/archiver.h @@ -40,7 +40,8 @@ enum SDArchiverStateReturns { SDAS_FAILED_TO_WRITE, SDAS_NO_COMPRESSOR, SDAS_NO_DECOMPRESSOR, - SDAS_INVALID_PARSED_STATE + SDAS_INVALID_PARSED_STATE, + SDAS_INVALID_FILE }; SDArchiverState *simple_archiver_init_state(const SDArchiverParsed *parsed); @@ -51,4 +52,7 @@ void simple_archiver_free_state(SDArchiverState **state); int simple_archiver_write_all(FILE *out_f, SDArchiverState *state, const SDArchiverLinkedList *filenames); +/// Returns zero on success. +int simple_archiver_print_archive_info(FILE *in_f); + #endif diff --git a/src/main.c b/src/main.c index 8582f52..a70970b 100644 --- a/src/main.c +++ b/src/main.c @@ -39,7 +39,7 @@ int main(int argc, const char **argv) { simple_archiver_parse_args(argc, argv, &parsed); - if ((parsed.flags & 0x4) == 0) { + if ((parsed.flags & 0x3) == 0 && (parsed.flags & 0x4) == 0) { FILE *file = fopen(parsed.filename, "r"); if (file != NULL) { fclose(file); @@ -55,10 +55,12 @@ int main(int argc, const char **argv) { SDArchiverLinkedList *filenames = simple_archiver_parsed_to_filenames(&parsed); - fprintf(stderr, "Filenames:\n"); - simple_archiver_list_get(filenames, print_list_fn, NULL); + if (filenames->count > 0) { + fprintf(stderr, "Filenames:\n"); + simple_archiver_list_get(filenames, print_list_fn, NULL); + } - if ((parsed.flags & 1) == 0) { + if ((parsed.flags & 3) == 0) { FILE *file = fopen(parsed.filename, "wb"); if (!file) { fprintf(stderr, "ERROR: Failed to open \"%s\" for writing!\n", @@ -70,7 +72,19 @@ int main(int argc, const char **argv) { SDArchiverState *state = simple_archiver_init_state(&parsed); if (simple_archiver_write_all(file, state, filenames) != SDAS_SUCCESS) { - fprintf(stderr, "Error during writing."); + fprintf(stderr, "Error during writing.\n"); + } + fclose(file); + } else if ((parsed.flags & 3) == 2) { + FILE *file = fopen(parsed.filename, "rb"); + if (!file) { + fprintf(stderr, "ERROR: Failed to open \"%s\" for reading!\n", + parsed.filename); + return 3; + } + + if (simple_archiver_print_archive_info(file) != 0) { + fprintf(stderr, "Error during archive checking/examining.\n"); } fclose(file); }