From 1606f479db5be38f1c5ced4057c92d99b1207951 Mon Sep 17 00:00:00 2001 From: lisk77 Date: Thu, 28 Aug 2025 16:15:16 +0200 Subject: [PATCH] feat(basefiles): added the BaseFileBuffer with BaseFileInfo and its core functionality to track files in the repo --- include/base_file_buffer.h | 24 ++++ src/base_file_buffer.c | 220 +++++++++++++++++++++++++++++++++++++ 2 files changed, 244 insertions(+) create mode 100644 include/base_file_buffer.h create mode 100644 src/base_file_buffer.c diff --git a/include/base_file_buffer.h b/include/base_file_buffer.h new file mode 100644 index 0000000..5d648e7 --- /dev/null +++ b/include/base_file_buffer.h @@ -0,0 +1,24 @@ +#ifndef BASE_FILE_BUFFER_H +#define BASE_FILE_BUFFER_H + +#include + +#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 diff --git a/src/base_file_buffer.c b/src/base_file_buffer.c new file mode 100644 index 0000000..93bcde8 --- /dev/null +++ b/src/base_file_buffer.c @@ -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; +}