Add a customization option for rsync's flags

This commit is contained in:
Tomas Rivera
2026-04-17 13:19:43 +02:00
parent a458a5bc3d
commit c063a6abe3
8 changed files with 55 additions and 29 deletions
+1
View File
@@ -6,3 +6,4 @@ error.log
output.log
result
massif.out.*
*.out.*
+3 -2
View File
@@ -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)
+1
View File
@@ -7,5 +7,6 @@ pkgs.mkShell {
pkgs.pkg-config
pkgs.gdb
pkgs.valgrind
pkgs.kdePackages.kcachegrind
];
}
+31 -10
View File
@@ -1,6 +1,8 @@
#include "cjson/cJSON.h"
#include "ui.h"
#include "utils.h"
#include "notes.h"
#include <stdlib.h>
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
+1 -1
View File
@@ -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();
+15 -14
View File
@@ -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);
}
}
+3 -2
View File
@@ -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
BIN
View File
Binary file not shown.