feat(basefiles): added the BaseFileBuffer with BaseFileInfo and its core functionality to track files in the repo
This commit is contained in:
parent
a3ee042758
commit
1606f479db
2 changed files with 244 additions and 0 deletions
24
include/base_file_buffer.h
Normal file
24
include/base_file_buffer.h
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
#ifndef BASE_FILE_BUFFER_H
|
||||
#define BASE_FILE_BUFFER_H
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include "utilities.h"
|
||||
|
||||
typedef struct {
|
||||
size_t base_num;
|
||||
size_t diff_num;
|
||||
char* name;
|
||||
} BaseFileInfo;
|
||||
|
||||
typedef List BaseFileBuffer;
|
||||
|
||||
BaseFileBuffer* base_file_buffer_new();
|
||||
int base_file_buffer_push(BaseFileBuffer*, BaseFileInfo);
|
||||
void base_file_buffer_free(BaseFileBuffer*);
|
||||
void base_file_buffer_sort(BaseFileBuffer*);
|
||||
BaseFileInfo* base_file_buffer_search(BaseFileBuffer*, char*);
|
||||
int read_base_file_list(BaseFileBuffer*, char*);
|
||||
int write_base_file_list(BaseFileBuffer*, char*);
|
||||
|
||||
#endif // BASE_FILE_BUFFER_H
|
||||
220
src/base_file_buffer.c
Normal file
220
src/base_file_buffer.c
Normal file
|
|
@ -0,0 +1,220 @@
|
|||
#include "base_file_buffer.h"
|
||||
|
||||
BaseFileBuffer* base_file_buffer_new() {
|
||||
return list_new(sizeof(BaseFileInfo));
|
||||
}
|
||||
|
||||
int base_file_buffer_push(BaseFileBuffer* buffer, BaseFileInfo info) {
|
||||
return list_push(buffer, &info);
|
||||
}
|
||||
|
||||
void base_file_buffer_free(BaseFileBuffer* buffer) {
|
||||
if (buffer) {
|
||||
for (int i = 0; i < buffer->len; i++) {
|
||||
free(((BaseFileInfo*)buffer->items+i)->name);
|
||||
}
|
||||
free(buffer->items);
|
||||
free(buffer);
|
||||
}
|
||||
}
|
||||
|
||||
int compare_base_file_info(const void* a, const void* b) {
|
||||
const BaseFileInfo* info1 = (const BaseFileInfo*)a;
|
||||
const BaseFileInfo* info2 = (const BaseFileInfo*)b;
|
||||
|
||||
return strcmp(info1->name, info2->name);
|
||||
}
|
||||
|
||||
void base_file_buffer_sort(BaseFileBuffer* buffer) {
|
||||
if (!buffer || buffer->len <= 1) {
|
||||
return;
|
||||
}
|
||||
|
||||
qsort(buffer->items, buffer->len, sizeof(BaseFileInfo), compare_base_file_info);
|
||||
}
|
||||
|
||||
BaseFileInfo* base_file_buffer_search(BaseFileBuffer* buffer, char* filename) {
|
||||
if (!buffer || !filename) return NULL;
|
||||
|
||||
BaseFileInfo search_key = (BaseFileInfo){.base_num = 0, .diff_num=0, .name = filename};
|
||||
|
||||
return (BaseFileInfo*)list_binary_search(buffer, &search_key, compare_base_file_info);
|
||||
}
|
||||
|
||||
int read_base_file_list(BaseFileBuffer* buffer, char* base_file_list_path) {
|
||||
size_t compressed_size;
|
||||
unsigned char* compressed_data = (unsigned char*)get_file_content_with_size(base_file_list_path, &compressed_size);
|
||||
|
||||
if (!compressed_data || compressed_size == 0) {
|
||||
free(compressed_data);
|
||||
return 1;
|
||||
}
|
||||
|
||||
char base_file_list[4096];
|
||||
uLongf dest_len = sizeof(base_file_list) - 1;
|
||||
|
||||
int result = uncompress((unsigned char*)base_file_list, &dest_len, compressed_data, compressed_size);
|
||||
free(compressed_data);
|
||||
|
||||
if (result != Z_OK) {
|
||||
perror("ERROR: decompression of the base file list failed!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
base_file_list[dest_len] = '\0';
|
||||
|
||||
size_t list_len = strlen(base_file_list);
|
||||
if (list_len == 0) return 1;
|
||||
size_t idx = 0;
|
||||
char current;
|
||||
|
||||
while (idx < list_len && IS_DIGIT(base_file_list[idx])) {
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (idx == 0) {
|
||||
perror("ERROR: no length found at start of base_file_list!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
char* len_str = calloc(idx + 1, sizeof(char));
|
||||
memcpy(len_str, base_file_list, idx);
|
||||
len_str[idx] = '\0';
|
||||
|
||||
char* end;
|
||||
long len = strtol(len_str, &end, 10);
|
||||
if (end == len_str || *end != '\0') {
|
||||
perror("ERROR: invalid length in read_base_file_list!");
|
||||
free(len_str);
|
||||
return 0;
|
||||
}
|
||||
free(len_str);
|
||||
|
||||
if (idx < list_len && base_file_list[idx] == ' ') {
|
||||
idx++;
|
||||
}
|
||||
|
||||
for (int i = 0; i < len; i++) {
|
||||
BaseFileInfo info;
|
||||
|
||||
size_t name_start = idx;
|
||||
while (idx < list_len && base_file_list[idx] != ' ') {
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (idx == name_start) {
|
||||
perror("ERROR: empty filename in base_file_list!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t name_len = idx - name_start;
|
||||
char* file_name = calloc(name_len + 1, sizeof(char));
|
||||
memcpy(file_name, base_file_list + name_start, name_len);
|
||||
file_name[name_len] = '\0';
|
||||
info.name = file_name;
|
||||
|
||||
if (idx < list_len && base_file_list[idx] == ' ') {
|
||||
idx++;
|
||||
}
|
||||
|
||||
size_t base_start = idx;
|
||||
while (idx < list_len && IS_DIGIT(base_file_list[idx])) {
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (idx == base_start) {
|
||||
perror("ERROR: no base_num found in base_file_list!");
|
||||
free(file_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t base_len = idx - base_start;
|
||||
char* base_num_str = calloc(base_len + 1, sizeof(char));
|
||||
memcpy(base_num_str, base_file_list + base_start, base_len);
|
||||
base_num_str[base_len] = '\0';
|
||||
|
||||
long base_num = strtol(base_num_str, &end, 10);
|
||||
if (end == base_num_str || *end != '\0') {
|
||||
perror("ERROR: invalid base_num in base_file_list!");
|
||||
free(file_name);
|
||||
free(base_num_str);
|
||||
return 0;
|
||||
}
|
||||
info.base_num = base_num;
|
||||
free(base_num_str);
|
||||
|
||||
if (idx < list_len && base_file_list[idx] == ' ') {
|
||||
idx++;
|
||||
}
|
||||
|
||||
size_t diff_start = idx;
|
||||
while (idx < list_len && IS_DIGIT(base_file_list[idx])) {
|
||||
idx++;
|
||||
}
|
||||
|
||||
if (idx == diff_start) {
|
||||
perror("ERROR: no diff_num found in base_file_list!");
|
||||
free(file_name);
|
||||
return 0;
|
||||
}
|
||||
|
||||
size_t diff_len = idx - diff_start;
|
||||
char* diff_num_str = calloc(diff_len + 1, sizeof(char));
|
||||
memcpy(diff_num_str, base_file_list + diff_start, diff_len);
|
||||
diff_num_str[diff_len] = '\0';
|
||||
|
||||
long diff_num = strtol(diff_num_str, &end, 10);
|
||||
if (end == diff_num_str || *end != '\0') {
|
||||
perror("ERROR: invalid diff_num in base_file_list!");
|
||||
free(file_name);
|
||||
free(diff_num_str);
|
||||
return 0;
|
||||
}
|
||||
info.diff_num = diff_num;
|
||||
free(diff_num_str);
|
||||
|
||||
if (i < len - 1 && idx < list_len && base_file_list[idx] == ' ') {
|
||||
idx++;
|
||||
}
|
||||
|
||||
base_file_buffer_push(buffer, info);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int write_base_file_list(BaseFileBuffer* buffer, char* info_file) {
|
||||
base_file_buffer_sort(buffer);
|
||||
char tmp[1024];
|
||||
size_t offset = 0;
|
||||
|
||||
offset += snprintf(tmp + offset, sizeof(tmp) - offset, "%d ", buffer->len);
|
||||
|
||||
for (size_t idx = 0; idx < buffer->len; idx++) {
|
||||
size_t remaining = sizeof(tmp) - offset;
|
||||
BaseFileInfo* info = (BaseFileInfo*)buffer->items + idx;
|
||||
offset += snprintf(tmp + offset, remaining, "%s %zu %zu ",
|
||||
info->name, info->base_num, info->diff_num);
|
||||
}
|
||||
|
||||
printf("%s\n", tmp);
|
||||
|
||||
FILE* fp = fopen(info_file, "wb");
|
||||
if (!fp) { perror("ERROR: cannot open path in snapshot_tree!\n"); return 0; }
|
||||
|
||||
|
||||
uLong originalLen = strlen(tmp) + 1;
|
||||
|
||||
uLong compressedLen = compressBound(originalLen);
|
||||
Bytef compressed[compressedLen];
|
||||
|
||||
if (compress(compressed, &compressedLen, (const Bytef*)tmp, originalLen) != Z_OK) {
|
||||
perror("ERROR: compression failed in snapshot_tree!");
|
||||
return 0;
|
||||
}
|
||||
|
||||
fwrite(compressed, sizeof(Bytef), compressedLen, fp);
|
||||
fclose(fp);
|
||||
|
||||
return 1;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue