Merge pull request 'Quick wins: ControlMaster, -z alias, --progress, fix write warning' (#6) from quick-wins into main

Reviewed-on: #6
This commit was merged in pull request #6.
This commit is contained in:
2026-07-16 12:30:13 +02:00
5 changed files with 35 additions and 4 deletions
+5 -1
View File
@@ -21,6 +21,8 @@ static void print_usage(void) {
printf("\n"); printf("\n");
printf("Options:\n"); printf("Options:\n");
printf(" -c [level] Enable compression (level 1-22, default 5)\n"); printf(" -c [level] Enable compression (level 1-22, default 5)\n");
printf(" -z [level] Alias for -c\n");
printf(" --progress Show transfer progress\n");
printf(" -m Enable multithreading\n"); printf(" -m Enable multithreading\n");
printf(" -s Enable chunk serialization\n"); printf(" -s Enable chunk serialization\n");
printf(" -f Enable sendfile (TCP only, not with -c or -s)\n"); printf(" -f Enable sendfile (TCP only, not with -c or -s)\n");
@@ -56,7 +58,7 @@ int main(int argc, char *argv[]) {
if (strcmp(argv[i], "--help") == 0) { if (strcmp(argv[i], "--help") == 0) {
print_usage(); print_usage();
return 0; return 0;
} else if (strcmp(argv[i], "-c") == 0) { } else if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "-z") == 0) {
config->use_compression = true; config->use_compression = true;
log_message(LOG_LEVEL_INFO, "Enabled Compression"); log_message(LOG_LEVEL_INFO, "Enabled Compression");
if (i + 1 < argc) { if (i + 1 < argc) {
@@ -94,6 +96,8 @@ int main(int argc, char *argv[]) {
server_host = str_dup(argv[++i]); server_host = str_dup(argv[++i]);
} else if (strcmp(argv[i], "--server-port") == 0 && i + 1 < argc) { } else if (strcmp(argv[i], "--server-port") == 0 && i + 1 < argc) {
server_port = atoi(argv[++i]); server_port = atoi(argv[++i]);
} else if (strcmp(argv[i], "--progress") == 0) {
config->show_progress = true;
} else if (strcmp(argv[i], "--chunk-size") == 0 && i + 1 < argc) { } else if (strcmp(argv[i], "--chunk-size") == 0 && i + 1 < argc) {
unsigned long long val = strtoull(argv[++i], NULL, 10); unsigned long long val = strtoull(argv[++i], NULL, 10);
if (val > 0) if (val > 0)
+23
View File
@@ -15,6 +15,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <threads.h> #include <threads.h>
#include <time.h>
int send_chunk(Client *client, Chunk *chunk, Config *config) { int send_chunk(Client *client, Chunk *chunk, Config *config) {
if (config->use_chunk_serialization) { if (config->use_chunk_serialization) {
@@ -140,16 +141,38 @@ int send_files(Config *config) {
config_send(client->file_descriptor, config); config_send(client->file_descriptor, config);
DirectoryScanner *scanner = directory_scanner_create(config->send_directory, config->use_metadata, config->chunk_size); DirectoryScanner *scanner = directory_scanner_create(config->send_directory, config->use_metadata, config->chunk_size);
Chunk *current_chunk; Chunk *current_chunk;
unsigned long long total_bytes = 0;
time_t last_progress = 0;
time_t start = time(NULL);
while ((current_chunk = directory_scanner_next(scanner)) != NULL) { while ((current_chunk = directory_scanner_next(scanner)) != NULL) {
unsigned long long chunk_bytes = 0;
for (int i = 0; i < current_chunk->element_count; i++)
chunk_bytes += current_chunk->items[i]->data->size;
if (!config->use_sendfile) { if (!config->use_sendfile) {
for (int i = 0; i < current_chunk->element_count; i++) for (int i = 0; i < current_chunk->element_count; i++)
file_load_data(current_chunk->items[i]); file_load_data(current_chunk->items[i]);
} }
send_chunk(client, current_chunk, config); send_chunk(client, current_chunk, config);
if (config->show_progress) {
total_bytes += chunk_bytes;
time_t now = time(NULL);
if (now - last_progress >= 1) {
last_progress = now;
double elapsed = difftime(now, start);
double rate = elapsed > 0 ? total_bytes / (1048576.0 * elapsed) : 0;
fprintf(stderr, "\rSent %.1f MB (%.1f MB/s) ", total_bytes / 1048576.0, rate);
fflush(stderr);
}
}
chunk_destroy(current_chunk); chunk_destroy(current_chunk);
} }
send_status(client->file_descriptor, STATUS_FINISHED); send_status(client->file_descriptor, STATUS_FINISHED);
int ok = receive_status(client->file_descriptor) == STATUS_OK; int ok = receive_status(client->file_descriptor) == STATUS_OK;
if (config->show_progress) {
double elapsed = difftime(time(NULL), start);
double rate = elapsed > 0 ? total_bytes / (1048576.0 * elapsed) : 0;
fprintf(stderr, "\rSent %.1f MB (%.1f MB/s) Done.\n", total_bytes / 1048576.0, rate);
}
directory_scanner_destroy(scanner); directory_scanner_destroy(scanner);
client_disconnect(client); client_disconnect(client);
client_delete(client); client_delete(client);
+1
View File
@@ -22,6 +22,7 @@ Config *config_create(char *version, char *send_directory,
config->use_chunk_serialization = use_chunk_serialization; config->use_chunk_serialization = use_chunk_serialization;
config->use_compression = use_compression; config->use_compression = use_compression;
config->use_metadata = use_metadata; config->use_metadata = use_metadata;
config->show_progress = false;
config->compression_level = compression_level; config->compression_level = compression_level;
config->use_sendfile = use_sendfile; config->use_sendfile = use_sendfile;
config->chunk_size = chunk_size > 0 ? chunk_size : DEFAULT_CHUNK_SIZE; config->chunk_size = chunk_size > 0 ? chunk_size : DEFAULT_CHUNK_SIZE;
+1
View File
@@ -18,6 +18,7 @@ typedef struct Config {
bool use_compression; bool use_compression;
bool use_sendfile; bool use_sendfile;
bool use_metadata; bool use_metadata;
bool show_progress;
int compression_level; int compression_level;
unsigned long long chunk_size; unsigned long long chunk_size;
TransportType transport; TransportType transport;
+5 -3
View File
@@ -91,10 +91,12 @@ Client *client_connect_ssh(char *destination) {
snprintf(ssh_user, sizeof(ssh_user), "%s", r.host); snprintf(ssh_user, sizeof(ssh_user), "%s", r.host);
execlp("ssh", "ssh", "-o", "Compression=no", "-o", execlp("ssh", "ssh", "-o", "Compression=no", "-o",
"ControlMaster=no", ssh_user, "fastsync-server", "--stdio", "ControlMaster=auto", "-o",
(char *)NULL); "ControlPath=~/.cache/fastsync-%r@%h:%p", ssh_user,
"fastsync-server", "--stdio", (char *)NULL);
perror("exec of ssh failed"); perror("exec of ssh failed");
(void)write(exec_pipe[1], "x", 1); ssize_t wret = write(exec_pipe[1], "x", 1);
(void)wret;
_exit(1); _exit(1);
} }