diff --git a/include/base_file_buffer.h b/include/base_file_buffer.h index d6e9cc5..4fbc7a3 100644 --- a/include/base_file_buffer.h +++ b/include/base_file_buffer.h @@ -21,5 +21,6 @@ BaseFileInfo* base_file_buffer_search(BaseFileBuffer*, char*); int base_file_buffer_remove(BaseFileBuffer*, char*); int read_base_file_list(BaseFileBuffer*, char*); int write_base_file_list(BaseFileBuffer*, char*); +FileInfoBuffer* basefilebuffer_to_fileinfobuffer(BaseFileBuffer*); #endif // BASE_FILE_BUFFER_H diff --git a/src/base_file_buffer.c b/src/base_file_buffer.c index 2052af0..b1a68d3 100644 --- a/src/base_file_buffer.c +++ b/src/base_file_buffer.c @@ -57,23 +57,66 @@ int read_base_file_list(BaseFileBuffer* buffer, char* base_file_list_path) { return 1; } - char base_file_list[4096]; - uLongf dest_len = sizeof(base_file_list) - 1; + size_t idx = 0; + while (idx < compressed_size && IS_DIGIT(compressed_data[idx])) { + idx++; + } - int result = uncompress((unsigned char*)base_file_list, &dest_len, compressed_data, compressed_size); + if (idx == 0) { + perror("ERROR: no length found at start of base file list!"); + free(compressed_data); + return 0; + } + + char* size_str = calloc(idx + 1, sizeof(char)); + if (!size_str) { + free(compressed_data); + return 0; + } + + memcpy(size_str, compressed_data, idx); + size_str[idx] = '\0'; + + char* end; + long original_size = strtol(size_str, &end, 10); + if (end == size_str || *end != '\0') { + perror("ERROR: invalid length in read_base_file_list!"); + free(size_str); + free(compressed_data); + return 0; + } + free(size_str); + + if (idx < compressed_size && compressed_data[idx] == ' ') { + idx++; + } + + char* base_file_list = calloc(original_size + 1, sizeof(char)); + if (!base_file_list) { + free(compressed_data); + return 0; + } + + uLongf dest_len = (uLongf)original_size; + + int result = uncompress((unsigned char*)base_file_list, &dest_len, compressed_data + idx, compressed_size - idx); free(compressed_data); if (result != Z_OK) { perror("ERROR: decompression of the base file list failed!"); + free(base_file_list); 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; + if (list_len == 0) { + free(base_file_list); + return 1; + } + + idx = 0; while (idx < list_len && IS_DIGIT(base_file_list[idx])) { idx++; @@ -81,6 +124,7 @@ int read_base_file_list(BaseFileBuffer* buffer, char* base_file_list_path) { if (idx == 0) { perror("ERROR: no length found at start of base_file_list!"); + free(base_file_list); return 0; } @@ -88,11 +132,11 @@ int read_base_file_list(BaseFileBuffer* buffer, char* base_file_list_path) { 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); + free(base_file_list); return 0; } free(len_str); @@ -111,6 +155,7 @@ int read_base_file_list(BaseFileBuffer* buffer, char* base_file_list_path) { if (idx == name_start) { perror("ERROR: empty filename in base_file_list!"); + free(base_file_list); return 0; } @@ -132,6 +177,7 @@ int read_base_file_list(BaseFileBuffer* buffer, char* base_file_list_path) { if (idx == base_start) { perror("ERROR: no base_num found in base_file_list!"); free(file_name); + free(base_file_list); return 0; } @@ -145,6 +191,7 @@ int read_base_file_list(BaseFileBuffer* buffer, char* base_file_list_path) { perror("ERROR: invalid base_num in base_file_list!"); free(file_name); free(base_num_str); + free(base_file_list); return 0; } info.base_num = base_num; @@ -162,6 +209,7 @@ int read_base_file_list(BaseFileBuffer* buffer, char* base_file_list_path) { if (idx == diff_start) { perror("ERROR: no diff_num found in base_file_list!"); free(file_name); + free(base_file_list); return 0; } @@ -175,6 +223,7 @@ int read_base_file_list(BaseFileBuffer* buffer, char* base_file_list_path) { perror("ERROR: invalid diff_num in base_file_list!"); free(file_name); free(diff_num_str); + free(base_file_list); return 0; } info.diff_num = diff_num; @@ -187,12 +236,25 @@ int read_base_file_list(BaseFileBuffer* buffer, char* base_file_list_path) { base_file_buffer_push(buffer, info); } + free(base_file_list); return 1; } int write_base_file_list(BaseFileBuffer* buffer, char* info_file) { base_file_buffer_sort(buffer); - char tmp[1024]; + + size_t buffer_size = 1; + buffer_size += snprintf(NULL, 0, "%d ", buffer->len); + + for (size_t idx = 0; idx < buffer->len; idx++) { + BaseFileInfo* info = (BaseFileInfo*)buffer->items + idx; + buffer_size += 3 + + strlen(info->name) + + snprintf(NULL, 0, "%zu", info->base_num) + + snprintf(NULL, 0, "%zu", info->diff_num); + } + + char tmp[buffer_size]; size_t offset = 0; offset += snprintf(tmp + offset, sizeof(tmp) - offset, "%d ", buffer->len); @@ -209,19 +271,58 @@ int write_base_file_list(BaseFileBuffer* buffer, char* info_file) { 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 originalLen = strlen(tmp); uLong compressedLen = compressBound(originalLen); - Bytef compressed[compressedLen]; + Bytef* compressed = malloc(compressedLen); + if (!compressed) { + fclose(fp); + return 0; + } if (compress(compressed, &compressedLen, (const Bytef*)tmp, originalLen) != Z_OK) { perror("ERROR: compression failed in snapshot_tree!"); + free(compressed); + fclose(fp); return 0; } + fprintf(fp, "%lu ", originalLen); fwrite(compressed, sizeof(Bytef), compressedLen, fp); + fclose(fp); + free(compressed); return 1; } + +FileInfoBuffer* basefilebuffer_to_fileinfobuffer(BaseFileBuffer* base_buffer) { + if (!base_buffer) return NULL; + + FileInfoBuffer* file_buffer = file_info_buffer_new(); + if (!file_buffer) return NULL; + + for (size_t i = 0; i < base_buffer->len; i++) { + BaseFileInfo* base_info = (BaseFileInfo*)base_buffer->items + i; + + struct stat st; + if (stat(base_info->name, &st) != 0) { + continue; + } + + FileInfo file_info; + file_info.name = strdup(base_info->name); + if (!file_info.name) { + file_info_buffer_free(file_buffer); + return NULL; + } + file_info.mode = st.st_mode; + + if (!file_info_buffer_push(file_buffer, file_info)) { + free(file_info.name); + file_info_buffer_free(file_buffer); + return NULL; + } + } + + return file_buffer; +}