feat(config): add fuzzy flag and bump protocol to 2.9.0

-y/--fuzzy is receiver-side similar-file basis selection, so the receiver
must learn the flag: add a bool to Config, serialize it as a trailing field
on the config frame, and validate the received value.  Because the config
frame layout changed, PROTOCOL_VERSION moves to 2.9.0 (peers must match).
This commit is contained in:
2026-09-06 21:04:11 +02:00
parent 3815b82306
commit f099a6e20f
2 changed files with 27 additions and 6 deletions
+18 -5
View File
@@ -46,6 +46,7 @@ static void config_set_defaults(Config* config) {
config->size_only = false;
config->use_delta = false;
config->whole_file = false;
config->fuzzy = false;
config->modify_window = 0;
config->delta_block_size = DELTA_BLOCK_SIZE_DEFAULT;
config->delta_max_file_size = DELTA_MAX_FILE_SIZE;
@@ -152,9 +153,9 @@ static bool validate_received_config(const Config* config) {
valid_wire_bool(config->use_delete) && valid_wire_bool(config->use_incremental) &&
valid_wire_bool(config->size_only) && valid_wire_bool(config->ignore_times) &&
valid_wire_bool(config->use_delta) && valid_wire_bool(config->backup) &&
valid_wire_bool(config->remove_source_files) && valid_wire_bool(config->follow_symlinks) &&
valid_wire_bool(config->copy_links) && valid_wire_bool(config->safe_links) &&
valid_wire_bool(config->copy_unsafe_links) &&
valid_wire_bool(config->fuzzy) && valid_wire_bool(config->remove_source_files) &&
valid_wire_bool(config->follow_symlinks) && valid_wire_bool(config->copy_links) &&
valid_wire_bool(config->safe_links) && valid_wire_bool(config->copy_unsafe_links) &&
valid_wire_bool(config->preserve_hard_links) && valid_wire_bool(config->preserve_acls) &&
valid_wire_bool(config->preserve_xattrs) && valid_wire_bool(config->preserve_devices) &&
valid_wire_bool(config->preserve_sparse) && valid_wire_bool(config->ignore_existing) &&
@@ -453,6 +454,12 @@ static bool send_basis_options(int fd, const Config* c) {
return true;
}
/* -y/--fuzzy (receiver-side similar-file basis selection). Trailing field on
* the config frame; protocol 2.9.0. */
static bool send_fuzzy_option(int fd, const Config* c) {
return send_int(fd, c->fuzzy);
}
static bool receive_core_fields(int fd, Config* c) {
int value;
if (!receive_wire_bool(fd, &c->eight_bit_output))
@@ -624,12 +631,17 @@ static bool receive_basis_options(int fd, Config* c) {
return true;
}
static bool receive_fuzzy_option(int fd, Config* c) {
return receive_wire_bool(fd, &c->fuzzy);
}
bool config_send(int file_descriptor, const Config* config) {
protocol_session_set_max_alloc(NULL, config->max_alloc);
if (!send_core_fields(file_descriptor, config) || !send_delta_fields(file_descriptor, config) ||
!send_file_options(file_descriptor, config) ||
!send_selection_options(file_descriptor, config) ||
!send_resume_options(file_descriptor, config) || !send_basis_options(file_descriptor, config))
!send_resume_options(file_descriptor, config) ||
!send_basis_options(file_descriptor, config) || !send_fuzzy_option(file_descriptor, config))
return false;
Status status;
if (!receive_status(file_descriptor, &status))
@@ -662,7 +674,8 @@ Config* config_receive(int file_descriptor) {
!receive_file_options(file_descriptor, config) ||
!receive_selection_options(file_descriptor, config) ||
!receive_resume_options(file_descriptor, config) ||
!receive_basis_options(file_descriptor, config))
!receive_basis_options(file_descriptor, config) ||
!receive_fuzzy_option(file_descriptor, config))
goto error;
if (config->compress_choice[0] != '\0' && strcmp(config->compress_choice, "zstd") != 0 &&
strcmp(config->compress_choice, "none") != 0) {
+9 -1
View File
@@ -63,6 +63,14 @@ typedef struct Config {
bool size_only;
bool use_delta;
bool whole_file;
/* -y/--fuzzy: when a file must be transferred and the destination holds no
* usable file at the exact path, the receiver may reuse a SIMILAR-named
* existing regular file in the same destination directory as the delta
* basis so the sender transmits only the differences. Crosses the wire
* (the receiver performs the candidate search); the CLI implies
* --incremental + --delta because the similar-basis only matters on the
* receiver-driven delta path. Off by default. */
bool fuzzy;
int modify_window;
uint32_t delta_block_size;
unsigned long long delta_max_file_size;
@@ -206,7 +214,7 @@ typedef struct Config {
DelayUpdatesContext* delay_context;
} Config;
#define PROTOCOL_VERSION "2.8.0"
#define PROTOCOL_VERSION "2.9.0"
#define DEFAULT_CHUNK_SIZE (10 * 1024 * 1024)
/* Upper bound on total basis-dir entries (rsync caps --link-dest at 20). */
#define MAX_BASIS_DIRS 64