diff --git a/include/file.h b/include/file.h index 2226546..2003a99 100644 --- a/include/file.h +++ b/include/file.h @@ -6,6 +6,22 @@ #include #include #include +#include +#include + +#ifdef _WIN32 +#include +#ifndef PATH_MAX +#define PATH_MAX MAX_PATH +#endif +#else +#include +#ifndef PATH_MAX +#define PATH_MAX 4096 +#endif +#endif + +#include "hash.h" typedef struct { char** content; @@ -15,10 +31,17 @@ typedef struct { typedef struct { mode_t mode; char* name; + char* hash; } FileInfo; File* new_empty_file(); File* new_file(const char*); +File* from_string(char*); File* slice_file(File*, uint64_t, uint64_t); +File* copy_file(File* original); +int insert_line(File*, char*, size_t); +int delete_line(File*, size_t); +int snapshot_file(char*, char*, size_t, char*); +void free_file(File*); #endif // FILE_H diff --git a/src/file.c b/src/file.c index b4301cf..ed8e8d3 100644 --- a/src/file.c +++ b/src/file.c @@ -54,6 +54,50 @@ File* new_file(const char* path) { return file; } +File* from_string(char* string) { + if (!string) return NULL; + + size_t len = strlen(string); + if (len == 0) return new_empty_file(); + + char* buf = malloc(len + 1); + if (!buf) return NULL; + strcpy(buf, string); + + size_t count = 1; + for (size_t i = 0; i < len; ++i) { + if (buf[i] == '\n') count++; + } + if (buf[len-1] == '\n') count--; + + char** lines = count ? (char**)malloc(count * sizeof *lines) : NULL; + if (count && !lines) { + free(buf); + return NULL; + } + + size_t idx = 0; + lines[idx++] = buf; + for (size_t i = 0; i < len; ++i) { + if (buf[i] == '\n') { + if (i > 0 && buf[i-1] == '\r') buf[i-1] = '\0'; + buf[i] = '\0'; + if (i+1 < len) lines[idx++] = &buf[i+1]; + } + } + if (len > 0 && buf[len-1] == '\r') buf[len-1] = '\0'; + + File* file = calloc(1, sizeof(File)); + if (!file) { + free(lines); + free(buf); + return NULL; + } + file->content = lines; + file->lines = idx; + return file; +} + File* slice_file(File* original, uint64_t start, uint64_t end) { if (!original || (end < start) || (end > original->lines)) return NULL; @@ -68,6 +112,75 @@ File* slice_file(File* original, uint64_t start, uint64_t end) { return slice; } +File* copy_file(File* original) { + if (!original) return NULL; + + File* copy = calloc(1, sizeof(File)); + if (!copy) return NULL; + + copy->lines = original->lines; + if (original->lines == 0) { + copy->content = NULL; + return copy; + } + + copy->content = malloc(original->lines * sizeof(char*)); + if (!copy->content) { + free(copy); + return NULL; + } + + for (size_t i = 0; i < original->lines; i++) { + copy->content[i] = strdup(original->content[i]); + if (!copy->content[i]) { + for (size_t j = 0; j < i; j++) { + free(copy->content[j]); + } + free(copy->content); + free(copy); + return NULL; + } + } + + return copy; +} + +int insert_line(File* file, char* line, size_t idx) { + if (!file || !line || idx > file->lines) return 0; + + char** new_content = realloc(file->content, (file->lines + 1) * sizeof(char*)); + if (!new_content) return 0; + + file->content = new_content; + + for (size_t i = file->lines; i > idx; i--) { + file->content[i] = file->content[i - 1]; + } + + file->content[idx] = strdup(line); + file->lines++; + + return 1; +} + +int delete_line(File* file, size_t idx) { + if (!file || idx >= file->lines) return 0; + + free(file->content[idx]); + + for (size_t i = idx; i < file->lines - 1; i++) { + file->content[i] = file->content[i + 1]; + } + + char** new_content = realloc(file->content, (file->lines - 1) * sizeof(char*)); + if (file->lines - 1 > 0 && !new_content) return 0; + + file->content = new_content; + file->lines--; + + return 1; +} + int snapshot_file(char* path, char* root, size_t basefile_id, char* hash) { File* file = new_file(path); if (!file) return 1; @@ -92,9 +205,24 @@ int snapshot_file(char* path, char* root, size_t basefile_id, char* hash) { strcat(concat_file, content[i]); } + const char* basefile_prefix = "basefile "; + size_t prefix_len = strlen(basefile_prefix); + size_t content_len = prefix_len + total_len; + + char* final_content = calloc(content_len, sizeof(char)); + if (!final_content) { + free(concat_file); + return 1; + } + + strcat(final_content, basefile_prefix); + strcat(final_content, concat_file); + + free(concat_file); + 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); + snprintf(id, sizeof(id), "%s %d", path, basefile_id); + object_hash(BaseFileObject, id, hash); char dir_path[PATH_MAX]; char file_path[PATH_MAX]; @@ -106,24 +234,24 @@ int snapshot_file(char* path, char* root, size_t basefile_id, char* hash) { if (!fp) { perror("ERROR: cannot open path in snapshot_file!\n"); free(concat_file); - return 1; + return 0; } - uLong originalLen = strlen(concat_file) + 1; + uLong originalLen = strlen(final_content) + 1; uLong compressedLen = compressBound(originalLen); Bytef* compressed = malloc(compressedLen); if (!compressed) { fclose(fp); free(concat_file); - return 1; + return 0; } - if (compress(compressed, &compressedLen, (const Bytef*)concat_file, originalLen) != Z_OK) { + if (compress(compressed, &compressedLen, (const Bytef*)final_content, originalLen) != Z_OK) { perror("ERROR: compression failed in snapshot_file!"); free(compressed); free(concat_file); fclose(fp); - return 1; + return 0; } fprintf(fp, "%lu ", (unsigned long)originalLen); @@ -136,5 +264,16 @@ int snapshot_file(char* path, char* root, size_t basefile_id, char* hash) { free(compressed); free(concat_file); - return 0; + return 1; +} + +void free_file(File* file) { + if (!file) return; + + if (file->content) { + free(file->content[0]); // Free the buffer holding all lines + free(file->content); // Free the array of line pointers + } + + free(file); }