Deletion timing is now real and selected by the four rsync flags plus the plain --delete default. Wire protocol bumps to 2.8.0: two new config booleans (delete_during, delete_delay) are serialized and validated, joining the existing delete_before/delete_after. - Early modes (--delete-before, --delete-during/--del): the sender pre-scans the whole tree (paths only), transmits the keep-set manifest BEFORE any file data, and the receiver removes extras and acks STATUS_OK; the sender only streams data after the deletion committed. Deletion is thus performed even if a later transfer phase fails (rsync delete-before/during are destructive by definition). FastSync streams in a single scan so it cannot interleave per-directory like rsync delete-during; --delete-during selects the same engine mode as --delete-before (documented divergence). - Late/commit modes (plain --delete, --delete-after, --delete-delay): the manifest closes the data stream and deletion is committed only after STATUS_FINISHED proves the whole transfer succeeded, preserving FastSync's commit-style safety. --delete-delay converges with --delete-after because FastSync never snapshots the destination during data flow (documented). - The STATUS_MANIFEST frame is now self-delimiting and position-independent. Single-threaded receivers delete before the success frame; the -m receiver hands the keep-set to server.c, which commits the deletion only after the disk writer thread has drained (fixes a delete-vs-in-flight-temp race). - Every timing flag implies --delete; at most one timing flag is allowed. - Each timing flag implies --delete, matching rsync; conflicts are rejected.
82 lines
3.2 KiB
C
82 lines
3.2 KiB
C
#include "client_validation.h"
|
|
#include "delay_updates.h"
|
|
#include "log.h"
|
|
#include "usage.h"
|
|
#include <stdio.h>
|
|
|
|
/* Validate config after parsing. Returns true if valid. */
|
|
bool validate_config(const Config* config) {
|
|
if (!config->send_directory || !config->receive_root_directory) {
|
|
log_message(LOG_LEVEL_ERROR, "source and destination directories are required");
|
|
print_usage();
|
|
return false;
|
|
}
|
|
if (config->use_sendfile && (config->use_chunk_serialization || config->use_compression)) {
|
|
log_message(LOG_LEVEL_ERROR, "-f/--sendfile cannot be combined with -c (compression) or -s "
|
|
"(chunk serialization)");
|
|
return false;
|
|
}
|
|
if (config->compression_threads > 0 && !config->use_compression) {
|
|
log_message(LOG_LEVEL_ERROR, "--compress-threads requires compression (-c or -z)");
|
|
return false;
|
|
}
|
|
if (config->transport == TRANSPORT_SSH && config->use_sendfile) {
|
|
log_message(LOG_LEVEL_ERROR, "-f/--sendfile is not supported with SSH transport");
|
|
return false;
|
|
}
|
|
if (config->use_incremental && config->use_chunk_serialization) {
|
|
log_message(LOG_LEVEL_ERROR, "--incremental is not supported with -s (chunk serialization)");
|
|
return false;
|
|
}
|
|
if (config->skip_compress_set && config->use_chunk_serialization) {
|
|
log_message(LOG_LEVEL_ERROR,
|
|
"--skip-compress cannot be combined with -s (chunk serialization)");
|
|
return false;
|
|
}
|
|
if (config->use_delta && !config->whole_file && !config->use_incremental) {
|
|
log_message(LOG_LEVEL_ERROR, "--delta requires --incremental");
|
|
return false;
|
|
}
|
|
if (config->use_delta && !config->whole_file && config->use_chunk_serialization) {
|
|
log_message(LOG_LEVEL_ERROR, "--delta cannot be combined with -s (chunk serialization)");
|
|
return false;
|
|
}
|
|
if (config->use_delta && !config->whole_file && config->use_sendfile) {
|
|
log_message(LOG_LEVEL_ERROR, "--delta cannot be combined with -f (sendfile)");
|
|
return false;
|
|
}
|
|
if (config->log_file_format && !config->log_file) {
|
|
log_message(LOG_LEVEL_ERROR, "--log-file-format requires --log-file");
|
|
return false;
|
|
}
|
|
if (config->append || config->append_verify) {
|
|
fprintf(
|
|
stderr,
|
|
"Error: --append and --append-verify are not supported yet; refusing to ignore option\n");
|
|
return false;
|
|
}
|
|
if (config->use_tls) {
|
|
if (!config->tls_cert || !config->tls_key || !config->tls_ca) {
|
|
log_message(LOG_LEVEL_ERROR, "--tls requires --cert, --key, and --ca");
|
|
return false;
|
|
}
|
|
}
|
|
if (config->delay_updates && config->inplace) {
|
|
log_message(LOG_LEVEL_ERROR, "--delay-updates does not work with --inplace");
|
|
return false;
|
|
}
|
|
if (config->delay_updates && delay_updates_staging_name_conflict(config->backup_dir)) {
|
|
log_message(LOG_LEVEL_ERROR,
|
|
"--backup-dir is reserved when --delay-updates is active (used for the internal "
|
|
"staging directory)");
|
|
return false;
|
|
}
|
|
if (!config_has_valid_delete_timing(config)) {
|
|
log_message(LOG_LEVEL_ERROR,
|
|
"--delete-before/--delete-during/--delete-delay/--delete-after select the delete "
|
|
"timing; at most one may be given and each implies --delete");
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|