feat(file): added utility functions to copy a file and insert/delete lines of the file
This commit is contained in:
parent
c8e5cd7095
commit
1dd9e2cbca
2 changed files with 170 additions and 8 deletions
|
|
@ -6,6 +6,22 @@
|
|||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <sys/stat.h>
|
||||
#include <math.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#ifndef PATH_MAX
|
||||
#define PATH_MAX MAX_PATH
|
||||
#endif
|
||||
#else
|
||||
#include <limits.h>
|
||||
#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
|
||||
|
|
|
|||
155
src/file.c
155
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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue