diff --git a/.gitignore b/.gitignore index d07b785..3151761 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,4 @@ error.log output.log result massif.out.* +*.out.* diff --git a/README.md b/README.md index 01b853d..e73c232 100644 --- a/README.md +++ b/README.md @@ -67,7 +67,8 @@ Change `~/.config/notewrapper/config.json`. If it does not exist, the program sh "backup": { "enable": false, "directory": "/path/to/backup", - "interval": "weekly" + "interval": "weekly", + "rsyncArgs": ["-Lqah", "--update"] } } ``` @@ -90,7 +91,7 @@ Change `~/.config/notewrapper/config.json`. If it does not exist, the program sh `backup.directory` is the directory where the backup will go. `backup.interval` can either be `daily`, `weekly`, `monthly` or an integer. It specifies the interval between two backups. - +`rsyncArgs` are the array of arguments that will be passed into rsync. See `man rsync` or `rsync --help`. ### What needs to be done (a lot) diff --git a/shell.nix b/shell.nix index c066d2a..da68d8c 100644 --- a/shell.nix +++ b/shell.nix @@ -7,5 +7,6 @@ pkgs.mkShell { pkgs.pkg-config pkgs.gdb pkgs.valgrind + pkgs.kdePackages.kcachegrind ]; } diff --git a/src/main.c b/src/main.c index d1fef68..525bbdb 100644 --- a/src/main.c +++ b/src/main.c @@ -1,6 +1,8 @@ +#include "cjson/cJSON.h" #include "ui.h" #include "utils.h" #include "notes.h" +#include int main(int argc, char *argv[]) { int shouldDebug = 0; @@ -177,12 +179,15 @@ arg_next: int doesBackup = 0; int interval = 0; // this is an int. But some times it will be inputed a string. We must translate it. char *pathToBackup = malloc(PATH_MAX); + char **rsyncArgs = NULL; + int rsyncArgsNumber = 0; cJSON *backupJSON = cJSON_GetObjectItem(json, "backup"); if (backupJSON && cJSON_IsObject(backupJSON)) { cJSON *doesBackupJSON = cJSON_GetObjectItem(backupJSON, "enable"); if (doesBackupJSON && cJSON_IsBool(doesBackupJSON)) { doesBackup = cJSON_IsTrue(doesBackupJSON) ? 1 : 0; debug("doesBackup is set to %d", doesBackup); + // handles the path to the backup cJSON *pathToBackupJSON = cJSON_GetObjectItem(backupJSON, "directory"); if (pathToBackupJSON && cJSON_IsString(pathToBackupJSON)) { char *temp = cJSON_GetStringValue(pathToBackupJSON); // we name it temp. As we can't directly set pathToBackup because snprintf doesn't like when a pointer is both an arg and the destination // temp should be freed when free(json), because cJSON_GetStringValue returns a pointer. @@ -192,30 +197,46 @@ arg_next: debug("~ was expanded to %s\nThe backup path is %s", homedir, pathToBackup); } else { pathToBackup = strndup(temp, PATH_MAX); // temp will be freed later so strndup - debug("Directory for backup is set to %s in config.json", pathToBackup); + debug("Directory for backup is set to %s in %s", pathToBackup, configPath); } - } else {error(1, "user", "config.json did not contained a directory inside the backup section or the value is from an unexpected type");} + } else {error(1, "user", "%s did not contained a directory inside the backup section or the value is from an unexpected type", configPath);} + // handles the interval of backup cJSON *intervalJSON = cJSON_GetObjectItem(backupJSON, "interval"); if (intervalJSON && cJSON_IsString(intervalJSON)) { char *temp = cJSON_GetStringValue(intervalJSON); // se comment higher. temp will be freed when calling free(json) if (strcmp(temp, "daily") == 0) { interval = DAILY; - debug("interval in config.json is set to \"daily\" which is %d", DAILY); + debug("interval in %s is set to \"daily\" which is %d", configPath, DAILY); } else if (strcmp(temp, "weekly") == 0) { interval = WEEKLY; - debug("interval in config.json is set to \"weekly\" which is %d", WEEKLY); + debug("interval in %s is set to \"weekly\" which is %d", configPath, WEEKLY); } else if (strcmp(temp, "monthly") == 0) { interval = MONTHLY; - debug("interval in config.json is set to \"monthly\" which is %d", MONTHLY); - } else {error(1, "user", "Unexpected string %s for entry \"interval\" in config.json. You must put an int (number of seconds) or \"daily\" or \"weekly\" or \"monthly\".", intervalJSON->valuestring);} + debug("interval in %s is set to \"monthly\" which is %d", configPath, MONTHLY); + } else {error(1, "user", "Unexpected string %s for entry \"interval\" in %s. You must put an int (number of seconds) or \"daily\" or \"weekly\" or \"monthly\".", intervalJSON->valuestring, configPath);} } else if (intervalJSON && cJSON_IsNumber(intervalJSON)) { interval = (int)cJSON_GetNumberValue(intervalJSON); - debug("interval in config.json is set to %d", interval); - } else {error(1, "user", "config.json did not contained an interval value inside the backup section or the value is from an unexpected type");} - } else{error(1, "user", "config.json did not contained a enable value inside the backup section or the value is from an unexpected type");} + debug("interval in %s is set to %d", configPath, interval); + } else {error(1, "user", "%s did not contained an interval value inside the backup section or the value is from an unexpected type", configPath);} + } else{error(1, "user", "%s did not contained a enable value inside the backup section or the value is from an unexpected type", configPath);} + // handle rsyncs array of arguments. + cJSON *rsyncArgsJSON = cJSON_GetObjectItem(backupJSON, "rsyncArgs"); + if (rsyncArgsJSON && cJSON_IsArray(rsyncArgsJSON)) { // if it is what we expected + rsyncArgsNumber = cJSON_GetArraySize(rsyncArgsJSON); + rsyncArgs = realloc(rsyncArgs, (size_t)rsyncArgsNumber); + for (int i = 0; i < rsyncArgsNumber; i++) { + cJSON *argJSON = cJSON_GetArrayItem(rsyncArgsJSON, i); + if (argJSON && cJSON_IsString(argJSON)) { + rsyncArgs[i] = cJSON_GetStringValue(argJSON); + } else {error(1, "user", "One element in rsyncArgs array in %s is not a string", configPath);} + } + } else {error(1, "user", "%s did not contained a rsyncArgs array inside the backup section or the value is from an unexpected type", configPath);} } else { debug("In %s, \"backup\" wasn't set or we encountered a abnormal type. Defaulting to {\"enable\": false}.", configPath); } + + + //cleans up cJSON_Delete(json); free(data); @@ -402,7 +423,7 @@ next_arg: debug("Finished parsing the attribute flags"); if (doesBackup) { // (TODO LATER) when implementing multiple directories for vault we should verifiy this works. - handleBackups(notesDirectoryString, pathToBackup, homedir, interval, shouldDebug); + handleBackups(notesDirectoryString, pathToBackup, homedir, interval, (const char**)rsyncArgs, rsyncArgsNumber, shouldDebug); } initscr(); //initialize ncurses diff --git a/src/ui.c b/src/ui.c index c82bc2b..77c69b9 100644 --- a/src/ui.c +++ b/src/ui.c @@ -24,7 +24,7 @@ input_screen: attroff(COLOR_PAIR(2)); } move(1, 1); // replace cursor - wgetnstr(stdscr, vaultName, sizeof(vaultName)-1); + wgetnstr(stdscr, vaultName, PATH_MAX-1); refresh(); endwin(); reset_shell_mode(); diff --git a/src/utils.c b/src/utils.c index 7e0d5fb..3fd1db3 100644 --- a/src/utils.c +++ b/src/utils.c @@ -70,7 +70,7 @@ void _error(const int shouldDebug, const int condition, const char *type, const } } -void copyDir(const char *source, const char *destination, const int shouldDebug) { +static void copyDir(const char *source, const char *destination, const char **rsyncArgs, const int rsyncArgsNumber, const int shouldDebug) { debug("Backuping... source: %s and destination: %s", source, destination); pid_t pid = fork(); @@ -78,16 +78,16 @@ void copyDir(const char *source, const char *destination, const int shouldDebug) if (pid == 0) { // Child process: execute rsync - char *args[] = { // (TODO LATER) - "rsync", - "-Lqah", // archive, follow links, human-readable // (TODO LATER) add a way to get verbose (-v) without it going on top of ncurses - "--progress", // show progress - "--update", // only update if newer - (char *)source, - (char *)destination, - NULL - }; - + char **args = malloc((4 + rsyncArgsNumber)*sizeof(char*)); + args[0] = "rsync"; + for (int i = 0; i < rsyncArgsNumber; i++) { + args[i+1] = (char *)rsyncArgs[i]; + if (i == rsyncArgsNumber-1) { // last loop + args[i+2] = (char*)source; + args[i+3] = (char*)destination; + args[i+4] = NULL; // execvp expect last arg to be NULL + } + } execvp("rsync", args); // If execvp returns, there was an error error(1, "program", "execvp() failed"); @@ -141,14 +141,15 @@ void initAppFilesAndDirs(const char *home, const int shouldDebug) { " \"backup\": {\n" " \"enable\": false,\n" " \"directory\": \"/path/to/backup\",\n" -" \"interval\": \"weekly\"\n" +" \"interval\": \"weekly\",\n" +" \"rsyncArgs\": [\"-Lqah\", \"--update\"]\n" " }\n" "}\n"); fclose(w); } -void handleBackups(const char *pathOfVaults, const char *pathOfBackup, const char *homeDir, const int interval, const int shouldDebug) { +void handleBackups(const char *pathOfVaults, const char *pathOfBackup, const char *homeDir, const int interval, const char **rsyncArguments, const int rsyncArgumentsNumber, const int shouldDebug) { int shouldBackup = 0; time_t now = time(NULL); debug("Time since epoch is %ld", (long)now); @@ -194,7 +195,7 @@ void handleBackups(const char *pathOfVaults, const char *pathOfBackup, const cha } if (shouldBackup) { - copyDir(pathOfVaults, pathOfBackup, shouldDebug); + copyDir(pathOfVaults, pathOfBackup, rsyncArguments, rsyncArgumentsNumber, shouldDebug); } } diff --git a/src/utils.h b/src/utils.h index a2d05cc..f3d5bf0 100644 --- a/src/utils.h +++ b/src/utils.h @@ -76,6 +76,7 @@ int openEditor(char *path, char *editor, int render, int shouldJumpToEndOfFile, // you should not forgot to free this string as it is in the heap. char *getFormatedTime(char *format, int shouldDebug); /* Caclulates if we need to do another backup (by reading ~/.cache/NoteWrapper/backupTime.txt. -If need launches in the background rsync to do the backuping.*/ -void handleBackups(const char *pathOfVaults, const char *pathOfBackup, const char *homeDir, const int interval, const int shouldDebug); +If need launches in the background rsync to do the backuping. +rsyncArgs is the array of arguments to be passed to rsync. Do not inclue destination or source. It will be added in the function.*/ +void handleBackups(const char *pathOfVaults, const char *pathOfBackup, const char *homeDir, const int interval, const char **rsyncArgs, const int rsyncArgsNumber, const int shouldDebug); #endif diff --git a/vgcore.2598850 b/vgcore.2598850 new file mode 100644 index 0000000..b3f2b89 Binary files /dev/null and b/vgcore.2598850 differ