rsync flags: -a, -n, -p, --exclude, --delete

Feature changes across 15 files:

- -a/--archive: enables -c -m -M (no -s, which slows transfers)
- -n/--dry-run: scan + print without connecting or transferring
- -p <port>: custom SSH port (passed as -p to ssh via execvp)
- --exclude <pattern>: glob-based filename filtering in scanner
- --delete: sender collects file manifest; receiver deletes unlisted files

Protocol: added STATUS_MANIFEST, use_delete field in Config wire format.
New utilities: glob_match(), delete_extras() with recursive directory walk.
Scanner: accepts exclude patterns; skips matching entries.
SSH transport: switched from execlp to execvp for dynamic port arg.
Server + multiprocessing: handle STATUS_MANIFEST in both single and
multithreaded receive paths.

Builds clean, all 7 tests pass.
This commit is contained in:
2026-07-16 12:39:05 +02:00
parent f778d1903c
commit 284bf8f8bc
15 changed files with 281 additions and 20 deletions
+13
View File
@@ -1,3 +1,4 @@
#include "array_list.h"
#include "chunk.h"
#include "compression.h"
#include "config.h"
@@ -55,6 +56,18 @@ int receive_files(Config *config, int file_descriptor) {
}
status = receive_status(file_descriptor);
}
if (status == STATUS_MANIFEST) {
int count = receive_int(file_descriptor);
ArrayList *manifest = array_list_create(free);
for (int i = 0; i < count; i++)
array_list_add(manifest, receive_str(file_descriptor));
fprintf(stderr, "Deleting files not in manifest...\n");
delete_extras(config->receive_root_directory, manifest);
for (int i = 0; i < manifest->size; i++)
free(manifest->items[i]);
array_list_delete(manifest);
status = receive_status(file_descriptor);
}
if (status != STATUS_FINISHED) {
log_message(LOG_LEVEL_ERROR, "Did not receive FINISHED Status");
send_status(file_descriptor, STATUS_ERROR);