diff --git a/src/file.c b/src/file.c index 8c32129..b4301cf 100644 --- a/src/file.c +++ b/src/file.c @@ -67,3 +67,74 @@ File* slice_file(File* original, uint64_t start, uint64_t end) { slice->lines = lines; return slice; } + +int snapshot_file(char* path, char* root, size_t basefile_id, char* hash) { + File* file = new_file(path); + if (!file) return 1; + + char** content = file->content; + size_t lines = file->lines; + size_t total_len = 0; + for (size_t i = 0; i < lines; i++) { + total_len += strlen(content[i]); + if (i < lines - 1) { + total_len++; + } + } + total_len += 1; + + char* concat_file = calloc(total_len, sizeof(char)); + if (!concat_file) return 1; + + strcpy(concat_file, content[0]); + for (size_t i = 1; i < lines; i++) { + strcat(concat_file, "\n"); + strcat(concat_file, content[i]); + } + + char id[2+snprintf(NULL, 0, "%d", basefile_id)+strlen(path)]; + snprintf(id, sizeof(id), "%s_%d", path, basefile_id); + object_hash(FileObject, id, hash); + + char dir_path[PATH_MAX]; + char file_path[PATH_MAX]; + snprintf(dir_path, sizeof(dir_path), "%s/.merk/objects/%.2s", root, hash); + mkdir(dir_path, 0755); + snprintf(file_path, sizeof(file_path), "%s/%s", dir_path, hash+2); + + FILE* fp = fopen(file_path, "wb"); + if (!fp) { + perror("ERROR: cannot open path in snapshot_file!\n"); + free(concat_file); + return 1; + } + + uLong originalLen = strlen(concat_file) + 1; + uLong compressedLen = compressBound(originalLen); + Bytef* compressed = malloc(compressedLen); + if (!compressed) { + fclose(fp); + free(concat_file); + return 1; + } + + if (compress(compressed, &compressedLen, (const Bytef*)concat_file, originalLen) != Z_OK) { + perror("ERROR: compression failed in snapshot_file!"); + free(compressed); + free(concat_file); + fclose(fp); + return 1; + } + + fprintf(fp, "%lu ", (unsigned long)originalLen); + + fwrite(compressed, 1, compressedLen, fp); + + fclose(fp); + + chmod(file_path, S_IRUSR | S_IRGRP | S_IROTH); + + free(compressed); + free(concat_file); + return 0; +}