grad_hw1: 0 length file handled + some comments
This commit is contained in:
parent
b51ea8df18
commit
63d93bb6c3
3 changed files with 112 additions and 11 deletions
25
list/list_int.c
Normal file
25
list/list_int.c
Normal 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
27
list/list_int.h
Normal 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
|
|
@ -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];
|
||||||
|
|
Reference in a new issue