summaryrefslogtreecommitdiff
path: root/src/backup.c
diff options
context:
space:
mode:
authorAargh Rai <shubh2007rai@gmail.com>2026-03-28 19:03:45 +0530
committerAargh Rai <shubh2007rai@gmail.com>2026-03-28 19:03:45 +0530
commitc7194b9b07a9c80344b52e002d0863fd258f0b38 (patch)
tree258e0aae8fdbdce64d8df36e75138a186358cd6b /src/backup.c
basic backup system, which utlizies regex for ignore files
Diffstat (limited to 'src/backup.c')
-rw-r--r--src/backup.c172
1 files changed, 172 insertions, 0 deletions
diff --git a/src/backup.c b/src/backup.c
new file mode 100644
index 0000000..d90d1d1
--- /dev/null
+++ b/src/backup.c
@@ -0,0 +1,172 @@
+#include "lib.h"
+#include <dirent.h>
+#include <regex.h>
+
+int check_path_type(const char* path) {
+ struct stat path_stat;
+ if (stat(path, &path_stat) != 0) {
+ return path_type_unknown;
+ }
+ if (S_ISDIR(path_stat.st_mode)) {
+ return path_type_directory;
+ }
+ return path_type_file;
+}
+
+int follows_ignore_rules(char* path, char* ignore_line) {
+ char lastbitofthepath[PATH_MAX];
+ int k = 0;
+ for (int i = 0; path[i] != 0; i++) {
+ if (path[i] == '/') {
+ lastbitofthepath[k] = 0;
+ k = 0;
+ continue;
+ }
+ lastbitofthepath[k++] = path[i];
+ }
+ if (k != 0 && lastbitofthepath[k] != 0) {
+ lastbitofthepath[k] = 0;
+ }
+
+ regex_t re;
+ int ret;
+
+ if (regcomp(&re, ignore_line, REG_EXTENDED) != 0) {
+ return 0;
+ }
+
+ ret = regexec(&re, lastbitofthepath, (size_t) 0, NULL, 0);
+ regfree(&re);
+
+ if (ret == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+int should_ignore(char* path, char* ignore_instructions, int VERBOSE) {
+ int i = 0, k = 0;
+ char line[PATH_MAX];
+ while (ignore_instructions[i] != 0) {
+ if (ignore_instructions[i] != '\n') {
+ line[k++] = ignore_instructions[i];
+ i++;
+ continue;
+ }
+ line[k] = 0;
+ k = 0;
+ if (!follows_ignore_rules(path, line)) {
+ i++;
+ continue;
+ }
+ if (VERBOSE) {
+ printf("Ignoring %s due to ignore rule %s\n", path, line);
+ }
+ return 1;
+ }
+ return 0;
+}
+
+void copy_to_backup(char* source_path, int VERBOSE) {
+ char destination_path[PATH_MAX];
+ int index_of_first_slash = -1;
+ for (int i = 0; i < PATH_MAX; i++) {
+ if (source_path[i] != '/') continue;
+ index_of_first_slash = i;
+ break;
+ }
+
+ if (index_of_first_slash == -1) {
+ // I DON'T EVEN KNOW HOW TO HANDLE THIS
+ fprintf(stderr, "Weird path issue encountered, failed to copy to source\nPath encountered: %s", source_path);
+ return;
+ }
+
+ int i = 0;
+ for (; i < index_of_first_slash; i++) {
+ destination_path[i] = source_path[i];
+ }
+ destination_path[i++] = '.';
+ destination_path[i++] = 'b';
+ destination_path[i] = 'k';
+ while (++i < PATH_MAX) {
+ destination_path[i] = source_path[i - 3];
+ }
+
+ if (VERBOSE) {
+ printf("%s -> %s\n", source_path, destination_path);
+ }
+
+ verify_parent_dirs_exist(destination_path, VERBOSE);
+
+ char command[2 * PATH_MAX + 10];
+ snprintf(command, 2 * PATH_MAX + 10, "cp \"%s\" \"%s\"", source_path, destination_path);
+ system(command);
+ if (VERBOSE) {
+ printf("Executing: %s\n", command);
+ }
+}
+
+void push(char* directories, int cursor, const char* to_add) {
+ int i = 0;
+ for (; to_add[i] != 0; i++) {
+ directories[cursor * PATH_MAX + i] = to_add[i];
+ }
+ while (i < PATH_MAX) {
+ directories[cursor * PATH_MAX + i++] = 0;
+ }
+}
+
+void backup(char* target, char* ignore_instructions, int VERBOSE) {
+ int file_type = check_path_type(target);
+ if (file_type != path_type_directory) {
+ fprintf(stderr, "Input not a directory\n");
+ return;
+ }
+
+ int cursor = 0;
+ char* directories = malloc(PATH_MAX * PATH_MAX * sizeof(*directories));
+ push(directories, cursor, target);
+ while (cursor != -1) {
+ char* path = &directories[(cursor--) * PATH_MAX];
+ DIR* dir_ptr = opendir(path);
+ if (dir_ptr == NULL) {
+ fprintf(stderr, "Couldn't open the directory: %s\n", path);
+ continue;
+ }
+
+ struct dirent* entry_ptr;
+ char full_path[PATH_MAX];
+ int i = 0;
+ for (; path[i] != 0; i++) {
+ full_path[i] = path[i];
+ }
+ full_path[i++] = '/';
+ while ((entry_ptr = readdir(dir_ptr)) != NULL) {
+ if (
+ strcmp(entry_ptr->d_name, ".") == 0 ||
+ strcmp(entry_ptr->d_name, "..") == 0
+ ) continue;
+ int j = 0;
+ for (; entry_ptr->d_name[j] != 0; j++) {
+ full_path[i + j] = entry_ptr->d_name[j];
+ }
+ full_path[i + j] = 0;
+
+ if (VERBOSE) {
+ printf("Looking at: %s\n", full_path);
+ }
+ if (should_ignore(full_path, ignore_instructions, VERBOSE)) {
+ continue;
+ }
+
+ if (entry_ptr->d_type == DT_REG) {
+ copy_to_backup(full_path, VERBOSE);
+ continue;
+ }
+ push(directories, ++cursor, full_path);
+ }
+ closedir(dir_ptr);
+ }
+}