From d2a47b1a5ae6548a55c038c72b4af1549c827cf5 Mon Sep 17 00:00:00 2001 From: Claudio Maggioni Date: Fri, 18 Oct 2019 09:43:32 +0200 Subject: [PATCH] grad_hw1: done --- .gitignore | 4 + splitter/splitter.c | 193 ++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 197 insertions(+) create mode 100644 splitter/splitter.c diff --git a/.gitignore b/.gitignore index 6bc2222..9feebf5 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ sortlines/sortlines **/.ccls-cache **/.gdb_history + +**/*.dSYM/**/* +splitter/splitter +*.o diff --git a/splitter/splitter.c b/splitter/splitter.c new file mode 100644 index 0000000..4a4699b --- /dev/null +++ b/splitter/splitter.c @@ -0,0 +1,193 @@ +// vim: set ts=2 sw=2 et tw=80: + +#include +#include +#include +#include + +const int MAX_SPLIT = 1024; +const int BUFFER_SIZE = 1024; + +int usage(); +int split(const char* filename, long max_size); +int merge(const char* index, const char* merged); + +inline int usage(const char* s) { + fprintf(stderr, "Usage: %s split [filename] [max-size]\n" + " %s merge [index] [merged]\n", s, s); + return 129; +} + +int main(int argc, char** const argv) { + if (argc != 4) return usage(argv[0]); + if (strcmp(argv[1], "split") == 0) { + long max = strtol(argv[3], NULL, 10); + if (max <= 0) { + return usage(argv[0]); + } + return split(argv[2], max); + } else if (strcmp(argv[1], "merge") == 0) { + return merge(argv[2], argv[3]); + } else { + return usage(argv[0]); + } +} + +unsigned char checksum(unsigned char start, + const unsigned char* buffer, long size) { + unsigned char sum = start; + for (long i = 0; i < size; i++) { + sum ^= buffer[i]; + } + return sum; +} + +int split(const char* filename, long max_size) { + FILE* source = fopen(filename, "r"); + if (source == NULL) { + perror("Cannot open source file"); + return 1; + } + + const int fnlen = strlen(filename); + char index_name[fnlen + 6]; // VLA + sprintf(index_name, "%s.index", filename); + FILE* index = fopen(index_name, "wx"); + + if (index == NULL) { + perror("Cannot create index file"); + fclose(source); + return 2; + } + + char part_name[fnlen + 10]; + unsigned char buffer[BUFFER_SIZE]; + + for(int part = 1; !feof(source); part++) { + // assign file name to part + sprintf(part_name, "%s.part%d", filename, part); + + FILE* part_file = fopen(part_name, "wx"); + + if (part_file == NULL) { + perror("Cannot create part file"); + fclose(source); + fclose(index); + return 4; + } + + unsigned char sum = 0x00; + + for (long i = max_size; i > 0 && !feof(source);) { + const long to_read = i > BUFFER_SIZE ? BUFFER_SIZE : i; + const long bytes = fread(buffer, 1, to_read, source); + + if (bytes == 0 || ferror(source)) { + perror("Cannot read source file"); + fclose(source); + fclose(index); + return 3; + } + + sum = checksum(sum, buffer, bytes); + + const long w_bytes = fwrite(buffer, 1, bytes, part_file); + + if (w_bytes == 0) { + perror("Cannot write on part file"); + fclose(source); + fclose(index); + fclose(part_file); + return 5; + } + + i -= bytes; + } + + if (fprintf(index, "%s %02x\n", part_name, sum) < 0) { + fprintf(stderr, "Cannot update index file"); + fclose(source); + fclose(index); + fclose(part_file); + return 6; + } + + fclose(part_file); + } + + fclose(source); + fclose(index); + return 0; +} + +int merge(const char* n_index, const char* n_merged) { + FILE* index = fopen(n_index, "r"); + + if (index == NULL) { + perror("Cannot open index file"); + return 7; + } + + FILE* merged = fopen(n_merged, "wx"); + + if (merged == NULL) { + perror("Cannot create merged file"); + fclose(index); + return 8; + } + + char part_name[strlen(n_index) + 100]; + + while(!feof(index)) { + unsigned int sum; + fscanf(index, "%s %x\n", part_name, &sum); + + FILE* part = fopen(part_name, "r"); + + if (part == NULL) { + perror("Cannot open part"); + fclose(index); + fclose(merged); + return 9; + } + + unsigned char check = 0x00; + while (!feof(part)) { + unsigned char buffer[1000]; + long bytes = fread(buffer, 1, 1000, part); + + if (ferror(part)) { + perror("Cannot read part"); + fclose(index); + fclose(merged); + fclose(part); + return 10; + } + + check = checksum(check, buffer, bytes); + fwrite(buffer, 1, bytes, merged); + + if (ferror(part)) { + perror("Cannot wrtite on merged"); + fclose(index); + fclose(merged); + fclose(part); + return 11; + } + } + + fclose(part); + + if ((unsigned char) sum != check) { + perror("Checksums differ for part"); + fclose(index); + fclose(merged); + fclose(part); + return 12; + } + } + + fclose(index); + fclose(merged); + return 0; +}