From 63d93bb6c3c9776198c8e26562634ed0ddd5ec44 Mon Sep 17 00:00:00 2001 From: Claudio Maggioni Date: Wed, 23 Oct 2019 16:03:59 +0200 Subject: [PATCH] grad_hw1: 0 length file handled + some comments --- list/list_int.c | 25 ++++++++++++++++ list/list_int.h | 27 +++++++++++++++++ splitter/splitter.c | 71 ++++++++++++++++++++++++++++++++++++++------- 3 files changed, 112 insertions(+), 11 deletions(-) create mode 100644 list/list_int.c create mode 100644 list/list_int.h diff --git a/list/list_int.c b/list/list_int.c new file mode 100644 index 0000000..0c26937 --- /dev/null +++ b/list/list_int.c @@ -0,0 +1,25 @@ +#include "list_int.h" + +struct list_int { + int data; + struct list_int* next; + struct list_int* prev; +} + +struct list_int* list_int_new() { + struct list_int* s = malloc(sizeof(struct list_int)); + if (!s) return s; + s->prev = NULL; + s->next = NULL; + s->data = 'S'; +} + +void list_int_delete(struct list_int* list) { +} + + +list_int_iterator list_int_erase(list_int_iterator i) { + if (i->next != i) { + struct list_int* m = i->next; + + diff --git a/list/list_int.h b/list/list_int.h new file mode 100644 index 0000000..45ff1d9 --- /dev/null +++ b/list/list_int.h @@ -0,0 +1,27 @@ +#ifndef LIST_INT_H_INCLUDED +#define LIST_INT_H_INCLUDED + +struct list_int; + +struct list_int * list_int_new (); /* constructor */ +void list_int_delete (struct list_int *); /* destructor */ + +typedef struct list_int * list_int_iterator; + +list_int_iterator list_int_append (struct list_int * l, int v); /* add at the end */ +list_int_iterator list_int_insert (list_int_iterator i, int v); /* add before i */ +list_int_iterator list_int_erase (list_int_iterator i); /* return next */ +void list_int_clear (struct list_int * l); + +list_int_iterator list_int_begin (struct list_int * l); +list_int_iterator list_int_end (struct list_int * l); + +int list_int_get (list_int_iterator i); +void list_int_put (list_int_iterator i, int v); + +int list_int_empty (list_int_iterator i); + +list_int_iterator list_int_next (list_int_iterator i); +list_int_iterator list_int_prev (list_int_iterator i); + +#endif diff --git a/splitter/splitter.c b/splitter/splitter.c index aa95561..65550cf 100644 --- a/splitter/splitter.c +++ b/splitter/splitter.c @@ -1,16 +1,50 @@ // vim: set ts=2 sw=2 et tw=80: +/* + * Assignment 1 - File Splitter + * Claudio Maggioni + * + * This code was written by using documentation on man(3) and cplusplus.com (C + * standard library section). + * + * The flag VERBOSE_ERRORS, if defined, activates proper error message handling + * and printing on stderr. This is disabled to comply with tests. + */ #include #include #include +#include -const int MAX_SPLIT = 1024; +/* + * Maximum number of part files expected, as defined by the assignment. By + * giving a size parameter too small thus having a number of part files greater + * than this may cause buffer overflows while handling part file names. + */ +const unsigned int MAX_SPLIT = 1024; + +/* + * Size of the byte buffer used in merge to read part file. Increase or decrease + * at will. + */ const int BUFFER_SIZE = 1024; +int digits(int); int usage(); int split(const char* filename, long max_size); -int merge(const char* index, const char* merged); +int merge(char* index, const char* merged); +/** + * Compute an appoximate figure of the number of decimal digits in an unsigned + * int by using an approximation of log base 8 (faster than log_10). Used only + * to compute the mamimum length of part filenames. + */ +inline int digits(int x) { + return (x ? (1 + digits(x << 3)) : 1); +} + +/* + * Print usage message on stderr if VERBOSE_ERRORS is enabled. + */ inline int usage(const char* s) { #ifdef VERBOSE_ERRORS fprintf(stderr, "Usage: %s split [filename] [max-size]\n" @@ -34,6 +68,10 @@ int main(int argc, char** const argv) { } } +/* + * Compute checksum on part files by using XOR. An initial value must be given + * in order to support computation of the checksum in chunks. + */ unsigned char checksum(unsigned char start, const unsigned char* buffer, long size) { unsigned char sum = start; @@ -43,6 +81,9 @@ unsigned char checksum(unsigned char start, return sum; } +/* + * Entire of split subcommand. Returns the exit status code. + */ int split(const char* filename, long max_size) { FILE* source = fopen(filename, "r"); if (source == NULL) { @@ -53,7 +94,10 @@ int split(const char* filename, long max_size) { } const int fnlen = strlen(filename); - char index_name[fnlen + 6]; // VLA + + // Compute the mamimum filename length and allocate a VLA to match that + char index_name[fnlen + strlen(".part") + digits(MAX_SPLIT) + 1]; + sprintf(index_name, "%s.index", filename); FILE* index = fopen(index_name, "wx"); @@ -75,11 +119,11 @@ int split(const char* filename, long max_size) { FILE* part_file = NULL; unsigned char sum = 0x00; - for (long i = max_size; i > 0 && !feof(source);) { - printf("%d %ld\n", part, i); + int first = part == 1; + for (long i = max_size; i > 0 && (!feof(source) || first);) { + const long to_read = i > BUFFER_SIZE ? BUFFER_SIZE : i; const long bytes = fread(buffer, 1, to_read, source); - printf("read %ld\n", bytes); if (ferror(source)) { #ifdef VERBOSE_ERRORS @@ -88,7 +132,7 @@ int split(const char* filename, long max_size) { fclose(source); fclose(index); return 3; - } else if (bytes == 0) { + } else if (bytes == 0 && part > 1) { goto all_read; } @@ -109,7 +153,7 @@ int split(const char* filename, long max_size) { const long w_bytes = fwrite(buffer, 1, bytes, part_file); - if (w_bytes == 0) { + if (w_bytes == 0 && !first) { #ifdef VERBOSE_ERRORS perror("Cannot write on part file"); #endif @@ -120,6 +164,7 @@ int split(const char* filename, long max_size) { } i -= bytes; + first = 0; } if (fprintf(index, "%s %02x\n", part_name, sum) < 0) { @@ -141,7 +186,7 @@ all_read: return 0; } -int merge(const char* n_index, const char* n_merged) { +int merge(char* n_index, const char* n_merged) { FILE* index = fopen(n_index, "r"); if (index == NULL) { @@ -161,11 +206,16 @@ int merge(const char* n_index, const char* n_merged) { return 8; } - char part_name[strlen(n_index) + 100]; + // Allocate enough memory to store the full path of each part + // We don't care about the .part suffix since the file name length contains + // .index which is already longer. VLAs again btw + char part_name[strlen(n_index) + digits(MAX_SPLIT) + 1]; + unsigned int n_part = 1; while(!feof(index)) { unsigned int sum; + fscanf(index, "%s %x\n", part_name, &sum); FILE* part = fopen(part_name, "r"); @@ -178,7 +228,6 @@ int merge(const char* n_index, const char* n_merged) { fclose(merged); return 9; } - unsigned char check = 0x00; while (!feof(part)) { unsigned char buffer[1000];