This repository has been archived on 2021-10-31. You can view files and clone it, but cannot push or open issues or pull requests.
sys_prog/splitter/splitter.c
Claudio Maggioni d2a47b1a5a grad_hw1: done
2019-10-18 09:43:32 +02:00

193 lines
4.1 KiB
C

// vim: set ts=2 sw=2 et tw=80:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
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;
}