grad_hw1: 0 length file handled + some comments

This commit is contained in:
Claudio Maggioni 2019-10-23 16:03:59 +02:00
parent b51ea8df18
commit 63d93bb6c3
3 changed files with 112 additions and 11 deletions

25
list/list_int.c Normal file
View file

@ -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;

27
list/list_int.h Normal file
View file

@ -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

View file

@ -1,16 +1,50 @@
// vim: set ts=2 sw=2 et tw=80: // 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 <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <libgen.h>
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; const int BUFFER_SIZE = 1024;
int digits(int);
int usage(); int usage();
int split(const char* filename, long max_size); 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) { inline int usage(const char* s) {
#ifdef VERBOSE_ERRORS #ifdef VERBOSE_ERRORS
fprintf(stderr, "Usage: %s split [filename] [max-size]\n" 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, unsigned char checksum(unsigned char start,
const unsigned char* buffer, long size) { const unsigned char* buffer, long size) {
unsigned char sum = start; unsigned char sum = start;
@ -43,6 +81,9 @@ unsigned char checksum(unsigned char start,
return sum; return sum;
} }
/*
* Entire of split subcommand. Returns the exit status code.
*/
int split(const char* filename, long max_size) { int split(const char* filename, long max_size) {
FILE* source = fopen(filename, "r"); FILE* source = fopen(filename, "r");
if (source == NULL) { if (source == NULL) {
@ -53,7 +94,10 @@ int split(const char* filename, long max_size) {
} }
const int fnlen = strlen(filename); 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); sprintf(index_name, "%s.index", filename);
FILE* index = fopen(index_name, "wx"); FILE* index = fopen(index_name, "wx");
@ -75,11 +119,11 @@ int split(const char* filename, long max_size) {
FILE* part_file = NULL; FILE* part_file = NULL;
unsigned char sum = 0x00; unsigned char sum = 0x00;
for (long i = max_size; i > 0 && !feof(source);) { int first = part == 1;
printf("%d %ld\n", part, i); for (long i = max_size; i > 0 && (!feof(source) || first);) {
const long to_read = i > BUFFER_SIZE ? BUFFER_SIZE : i; const long to_read = i > BUFFER_SIZE ? BUFFER_SIZE : i;
const long bytes = fread(buffer, 1, to_read, source); const long bytes = fread(buffer, 1, to_read, source);
printf("read %ld\n", bytes);
if (ferror(source)) { if (ferror(source)) {
#ifdef VERBOSE_ERRORS #ifdef VERBOSE_ERRORS
@ -88,7 +132,7 @@ int split(const char* filename, long max_size) {
fclose(source); fclose(source);
fclose(index); fclose(index);
return 3; return 3;
} else if (bytes == 0) { } else if (bytes == 0 && part > 1) {
goto all_read; 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); const long w_bytes = fwrite(buffer, 1, bytes, part_file);
if (w_bytes == 0) { if (w_bytes == 0 && !first) {
#ifdef VERBOSE_ERRORS #ifdef VERBOSE_ERRORS
perror("Cannot write on part file"); perror("Cannot write on part file");
#endif #endif
@ -120,6 +164,7 @@ int split(const char* filename, long max_size) {
} }
i -= bytes; i -= bytes;
first = 0;
} }
if (fprintf(index, "%s %02x\n", part_name, sum) < 0) { if (fprintf(index, "%s %02x\n", part_name, sum) < 0) {
@ -141,7 +186,7 @@ all_read:
return 0; 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"); FILE* index = fopen(n_index, "r");
if (index == NULL) { if (index == NULL) {
@ -161,11 +206,16 @@ int merge(const char* n_index, const char* n_merged) {
return 8; 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; unsigned int n_part = 1;
while(!feof(index)) { while(!feof(index)) {
unsigned int sum; unsigned int sum;
fscanf(index, "%s %x\n", part_name, &sum); fscanf(index, "%s %x\n", part_name, &sum);
FILE* part = fopen(part_name, "r"); FILE* part = fopen(part_name, "r");
@ -178,7 +228,6 @@ int merge(const char* n_index, const char* n_merged) {
fclose(merged); fclose(merged);
return 9; return 9;
} }
unsigned char check = 0x00; unsigned char check = 0x00;
while (!feof(part)) { while (!feof(part)) {
unsigned char buffer[1000]; unsigned char buffer[1000];