Merge remote-tracking branch 'origin/feat/8-bit-output' into dev

# Conflicts:
#	src/client/client_cli.c
#	src/client/client_send.c
#	src/shared/config.c
#	tests/test_client_cli.c
#	tests/test_config.c
#	tests/test_shared_utils.c
This commit is contained in:
2026-09-04 17:18:01 +02:00
21 changed files with 248 additions and 35 deletions
+22 -5
View File
@@ -156,6 +156,7 @@ static const OptionEntry OPTION_TABLE[] = {
{"--inplace", NULL, OPT_FLAG, offsetof(Config, inplace)},
{"--fsync", NULL, OPT_FLAG, offsetof(Config, use_fsync)},
{"--checksum", NULL, OPT_FLAG, offsetof(Config, checksum)},
{"--8-bit-output", "-8", OPT_FLAG, offsetof(Config, eight_bit_output)},
{"--source-dir", NULL, OPT_STRING, offsetof(Config, send_directory)},
{"--dest-dir", NULL, OPT_STRING, offsetof(Config, receive_root_directory)},
@@ -214,6 +215,7 @@ static int apply_table_option(Config* config, const OptionEntry* entry, const ch
int parse_args(Config* config, int argc, char* argv[], int* positional_args,
int* positional_count) {
bool verbose = false;
protocol_set_8_bit_output(config->eight_bit_output);
for (int i = 1; i < argc; i++) {
const OptionEntry* entry = find_table_option(argv[i]);
if (entry) {
@@ -227,6 +229,8 @@ int parse_args(Config* config, int argc, char* argv[], int* positional_args,
} else if (apply_table_option(config, entry, NULL) != 0) {
return -1;
}
if (entry->offset == offsetof(Config, eight_bit_output))
protocol_set_8_bit_output(true);
continue;
}
@@ -302,7 +306,10 @@ int parse_args(Config* config, int argc, char* argv[], int* positional_args,
log_message(LOG_LEVEL_INFO, "Enabled Chunk Serialization");
} else if (opt_is(argv[i], "--server-port", NULL) && i + 1 < argc) {
if (!parse_positive_int(argv[++i], &config->server_port)) {
log_message(LOG_LEVEL_ERROR, "invalid --server-port value: %s", argv[i]);
char* escaped = output_escape(argv[i], false);
log_message(LOG_LEVEL_ERROR, "invalid --server-port value: %s",
escaped ? escaped : "<allocation failed>");
free(escaped);
return -1;
}
if (config->server_port > 65535) {
@@ -340,7 +347,10 @@ int parse_args(Config* config, int argc, char* argv[], int* positional_args,
}
FILE* lf = fopen(argv[++i], "a");
if (!lf) {
log_message(LOG_LEVEL_ERROR, "could not open log file '%s': %s", argv[i], strerror(errno));
char* escaped = output_escape(argv[i], false);
log_message(LOG_LEVEL_ERROR, "could not open log file '%s': %s",
escaped ? escaped : "<allocation failed>", strerror(errno));
free(escaped);
return -1;
}
config->log_file = lf;
@@ -368,14 +378,18 @@ int parse_args(Config* config, int argc, char* argv[], int* positional_args,
return -1;
}
} else if (argv[i][0] == '-') {
fprintf(stderr, "Unknown option: %s\n", argv[i]);
char* escaped = output_escape(argv[i], false);
fprintf(stderr, "Unknown option: %s\n", escaped ? escaped : "<allocation failed>");
free(escaped);
print_usage();
return -1;
} else {
if (*positional_count < 2)
positional_args[(*positional_count)++] = i;
else {
fprintf(stderr, "Unexpected argument: %s\n", argv[i]);
char* escaped = output_escape(argv[i], false);
fprintf(stderr, "Unexpected argument: %s\n", escaped ? escaped : "<allocation failed>");
free(escaped);
print_usage();
return -1;
}
@@ -388,7 +402,10 @@ int parse_args(Config* config, int argc, char* argv[], int* positional_args,
static int read_patterns_from_file(const char* filepath, char*** patterns, int* count) {
FILE* fp = fopen(filepath, "r");
if (!fp) {
log_message(LOG_LEVEL_ERROR, "could not open pattern file '%s': %s", filepath, strerror(errno));
char* escaped = output_escape(filepath, false);
log_message(LOG_LEVEL_ERROR, "could not open pattern file '%s': %s",
escaped ? escaped : "<allocation failed>", strerror(errno));
free(escaped);
return -1;
}
char* line = NULL;
+9 -2
View File
@@ -233,11 +233,18 @@ static int send_dry_run_manifest(const Config* config) {
while ((chunk = directory_scanner_next(scanner)) != NULL) {
for (int i = 0; i < chunk->element_count; i++) {
if (!config->quiet) {
char* escaped_path = output_escape(chunk->items[i]->path, config->eight_bit_output);
if (!escaped_path) {
chunk_destroy(chunk);
directory_scanner_destroy(scanner);
return -1;
}
if (config->human_readable)
printf(" %s (%s)\n", chunk->items[i]->path,
printf(" %s (%s)\n", escaped_path,
display_bytes(chunk->items[i]->data->size, true, size_buffer, sizeof(size_buffer)));
else
printf(" %s (%zu bytes)\n", chunk->items[i]->path, chunk->items[i]->data->size);
printf(" %s (%zu bytes)\n", escaped_path, chunk->items[i]->data->size);
free(escaped_path);
}
total_bytes += chunk->items[i]->data->size;
file_count++;
+1
View File
@@ -21,6 +21,7 @@ void print_usage(void) {
printf(" --remove-source-files Remove regular source files after successful transfer\n");
printf(" -p <port> SSH port (default: 22)\n");
printf(" --progress Show transfer progress\n");
printf(" -8, --8-bit-output Leave high-bit characters unescaped in output\n");
printf(" --delete Delete files on receiver not in source\n");
printf(" --exclude <pattern> Exclude files matching pattern\n");
printf(" --include <pattern> Only include files matching pattern\n");