cleanup: remove dead code, fix bugs, refactor SSH dest parsing

- Remove debug printf calls from file.c
- Remove dead code: chunk_print, chunk_format, chunk_data_create/delete
- Remove unused config.use_single_send_per_file field
- Fix server_delete() no-op (double-pointer)
- Fix double cast (long)(long) -> ptrdiff_t in chunk.c
- Fix thread return value: thrd_error instead of 1
- Remove unused config param from receive_chunk_enqueue()
- Make queue_double_capacity() static
- Move SSH dest parsing into config.c as config_parse_ssh_dest()
- Fix test_config_ssh_dest to test parsing round-trip
- Remove chunk_format test (obsolete format)
- Replace chunk_data_delete with data_destroy in tests
This commit is contained in:
2026-07-07 19:07:24 +02:00
parent 783400d7e9
commit b3f69208ce
14 changed files with 69 additions and 189 deletions
+2 -19
View File
@@ -125,7 +125,7 @@ int send_chunks_multithreaded(void *pipeline_context) {
int ok = receive_status(client->file_descriptor) == STATUS_OK;
client_disconnect(client);
client_delete(client);
return ok ? thrd_success : 1;
return ok ? thrd_success : thrd_error;
}
if (send_chunk(client, current_chunk, context->config) != 0) {
perror("Something unexpected happend while sending the chunk");
@@ -189,16 +189,6 @@ int send_files_multithreaded(Config *config) {
return 0;
}
static int is_remote_dest(const char *s) {
const char *colon = strchr(s, ':');
if (!colon) return 0;
if (colon == s) return 0;
for (const char *p = s; p < colon; p++) {
if (*p == '/') return 0;
}
return 1;
}
static void print_usage(void) {
printf("Usage:\n");
printf(" fastsync [options] <source> <destination>\n");
@@ -307,14 +297,7 @@ int main(int argc, char *argv[]) {
config->receive_root_directory = str_dup(argv[positional_args[1]]);
config->save_to_disk = true;
if (is_remote_dest(config->receive_root_directory)) {
config->transport = TRANSPORT_SSH;
config->ssh_destination = str_dup(config->receive_root_directory);
char *colon = strchr(config->receive_root_directory, ':');
char *path = str_dup(colon + 1);
free(config->receive_root_directory);
config->receive_root_directory = path;
}
config_parse_ssh_dest(config);
} else if (positional_count == 1) {
fprintf(stderr, "Error: missing destination argument\n");
print_usage();
+5 -6
View File
@@ -30,16 +30,15 @@ File *file_receive(Config *config, int file_descriptor) {
return file;
}
static void receive_chunk_enqueue(int file_descriptor, Config *config,
static void receive_chunk_enqueue(int file_descriptor,
PipelineContextReceiver *context) {
(void)config;
Data *chunk_data = receive_data(file_descriptor);
Data *data_to_process = chunk_data;
if (config->use_compression) {
if (context->config->use_compression) {
data_to_process = data_decompress(chunk_data);
data_destroy(chunk_data);
}
Chunk *chunk = chunk_deserialize(data_to_process, config->use_metadata);
Chunk *chunk = chunk_deserialize(data_to_process, context->config->use_metadata);
data_destroy(data_to_process);
for (int i = 0; i < chunk->element_count; i++) {
@@ -63,7 +62,7 @@ int receive_thread(void *pipeline_context) {
Status status = receive_status(file_descriptor);
while (status == STATUS_NEXT || status == STATUS_CHUNK) {
if (status == STATUS_CHUNK) {
receive_chunk_enqueue(file_descriptor, config, context);
receive_chunk_enqueue(file_descriptor, context);
} else {
File *file = file_receive(config, file_descriptor);
queue_enqueue_multithreaded(context->queue, file, &context->mutex,
@@ -180,6 +179,6 @@ int main(int argc, char *argv[]) {
}
Server *server = server_create(8080);
server_listen(server, handler);
server_delete(server);
server_delete(&server);
return 0;
}
-71
View File
@@ -49,15 +49,6 @@ void chunk_destroy(void *item) {
free(chunk);
}
void chunk_print(void *item) {
if (item == NULL)
return;
Chunk *chunk = (Chunk *)item;
for (int i = 0; i < chunk->element_count; ++i)
if (chunk->items[i] != NULL)
file_print(chunk->items[i]);
}
static void metadata_to_buf(char **buf, FileMetadata *m) {
int present = (m != NULL) ? 1 : 0;
memcpy(*buf, &present, sizeof(int));
@@ -86,53 +77,6 @@ static FileMetadata *metadata_from_buf(char **buf) {
return m;
}
static unsigned long long per_file_chunk_format_size(File *file) {
return sizeof(int) + strlen(file->path) + sizeof(int) +
(file->metadata ? FILE_METADATA_WIRE_SIZE : 0) +
sizeof(unsigned long long) + file->data->size;
}
Data *chunk_format(Chunk *chunk) {
unsigned long long buffer_size = 0;
for (int i = 0; i < chunk->element_count; ++i) {
buffer_size += per_file_chunk_format_size(chunk->items[i]);
}
char *data = malloc(buffer_size);
if (data == NULL) {
perror("Could not allocate data for ChunkFormated!");
exit(EXIT_FAILURE);
}
char *current_data_pointer = data;
for (int i = 0; i < chunk->element_count; ++i) {
File *file = chunk->items[i];
// add path len
int path_length = (int)strlen(file->path);
memcpy(current_data_pointer, &path_length, sizeof(int));
current_data_pointer += sizeof(int);
// add path
memcpy(current_data_pointer, file->path, path_length);
current_data_pointer += path_length;
// add metadata
metadata_to_buf(&current_data_pointer, file->metadata);
// add file data len
unsigned long long file_length = file->data->size;
memcpy(current_data_pointer, &file_length, sizeof(unsigned long long));
current_data_pointer += sizeof(unsigned long long);
// add file data
if (file->data->data == NULL) {
file_load_data(file);
}
memcpy(current_data_pointer, file->data->data, file_length);
current_data_pointer += file_length;
}
if (current_data_pointer - data != (long)(long)buffer_size) {
perror("Buffer of Chunk wasn't filled enough!");
exit(EXIT_FAILURE);
}
return chunk_data_create(data, buffer_size);
}
static unsigned long long per_file_serialize_size(File *file, bool use_metadata) {
return sizeof(size_t) + strlen(file->path) +
(use_metadata ? sizeof(int) + (file->metadata ? FILE_METADATA_WIRE_SIZE : 0) : 0) +
@@ -284,19 +228,4 @@ Chunk *chunk_decompress(Data *compressed_data, bool use_metadata) {
return chunk;
}
Data *chunk_data_create(void *data, unsigned long long data_size) {
Data *chunk_formated = malloc(sizeof(Data));
if (chunk_formated == NULL) {
perror("Could not allocate memory for ChunkFormated");
exit(EXIT_FAILURE);
}
chunk_formated->data = data;
chunk_formated->size = data_size;
return chunk_formated;
}
void chunk_data_delete(void *chunk) {
Data *chunk_data = (Data *)chunk;
free(chunk_data->data);
free(chunk_data);
}
+1 -4
View File
@@ -15,13 +15,10 @@ typedef struct {
Chunk *chunk_create(File **items, int element_count);
void chunk_destroy(void *chunk);
void chunk_print(void *chunk);
Data *chunk_format(Chunk *chunk);
Data *chunk_serialize(Chunk *chunk, bool use_metadata);
Chunk *chunk_deserialize(Data *data, bool use_metadata);
Data *chunk_compress(Chunk *chunk, int compression_level, bool use_metadata);
Chunk *chunk_decompress(Data *compressed_data, bool use_metadata);
Data *chunk_data_create(void *data, unsigned long long data_size);
void chunk_data_delete(void *chunk);
#endif
+23
View File
@@ -1,8 +1,10 @@
#include "config.h"
#include "socket.h"
#include "utils.h"
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
Config *config_create(char *version, char *send_directory,
char *receive_directory, bool save_to_disk,
@@ -27,6 +29,27 @@ Config *config_create(char *version, char *send_directory,
return config;
}
bool is_remote_dest(const char *s) {
if (s == NULL) return false;
const char *colon = strchr(s, ':');
if (colon == NULL) return false;
if (colon == s) return false;
for (const char *p = s; p < colon; p++) {
if (*p == '/') return false;
}
return true;
}
void config_parse_ssh_dest(Config *config) {
if (!is_remote_dest(config->receive_root_directory)) return;
config->transport = TRANSPORT_SSH;
config->ssh_destination = str_dup(config->receive_root_directory);
char *colon = strchr(config->receive_root_directory, ':');
char *path = str_dup(colon + 1);
free(config->receive_root_directory);
config->receive_root_directory = path;
}
void config_delete(Config *config) {
free(config->version);
free(config->send_directory);
+2 -1
View File
@@ -17,7 +17,6 @@ typedef struct Config {
bool use_chunk_serialization;
bool use_compression;
bool use_sendfile;
bool use_single_send_per_file;
bool use_metadata;
int compression_level;
int num_connections;
@@ -33,5 +32,7 @@ Config *config_create(char *version, char *send_directory,
void config_delete(Config *config);
void config_send(int file_descriptor, Config *config);
Config *config_receive(int file_descriptor);
bool is_remote_dest(const char *s);
void config_parse_ssh_dest(Config *config);
#endif
-8
View File
@@ -80,7 +80,6 @@ void file_load_data(File *file) {
exit(EXIT_FAILURE);
}
}
printf("%ld is file big", file->data->size);
size_t bytes_read = file_content_to_buffer(file);
if (bytes_read != file->data->size) {
log_message(STATUS_ERROR, "Didnt read expected amount of bytes from file");
@@ -88,12 +87,6 @@ void file_load_data(File *file) {
}
}
void file_print(void *item) {
if (item == NULL)
return;
printf("%s\n", ((File *)item)->path);
}
static void metadata_send(int file_descriptor, FileMetadata *m) {
if (m == NULL) {
int zero = 0;
@@ -127,7 +120,6 @@ void file_send_single_calls(File *file, int file_descriptor, bool use_metadata)
send_str(file_descriptor, file->path);
if (use_metadata)
metadata_send(file_descriptor, file->metadata);
printf("Sending File: %ld", file->data->size);
send_data(file_descriptor, file->data->data, file->data->size);
}
-1
View File
@@ -22,7 +22,6 @@ typedef struct {
File *file_create(const char *path);
void file_destroy(void *item);
void file_load_data(File *file);
void file_print(void *item);
void file_send_single_calls(File *file, int file_descriptor, bool use_metadata);
void file_send_sendfile(File *file, int file_descriptor, bool use_metadata);
size_t file_content_to_buffer(File *file);
+1 -1
View File
@@ -59,7 +59,7 @@ bool queue_is_full(Queue *queue) {
return queue->size == queue->capacity;
}
void queue_double_capacity(Queue *queue) {
static void queue_double_capacity(Queue *queue) {
if (queue == NULL)
return;
unsigned int new_capacity = queue->capacity * 2;
-1
View File
@@ -17,7 +17,6 @@ Queue *queue_create(int capacity, void (*destroyer)(void *item));
void queue_destroy(Queue *queue);
bool queue_is_empty(Queue *queue);
bool queue_is_full(Queue *queue);
void queue_double_capacity(Queue *queue);
void queue_enqueue(Queue *queue, void *item);
void queue_enqueue_multithreaded(Queue *queue, void *item, mtx_t *mutex,
cnd_t *condition_not_empty,
+5 -4
View File
@@ -167,10 +167,11 @@ Server *server_create(int port) {
return server;
}
void server_delete(Server *server) {
free(server);
server = NULL;
};
void server_delete(Server **server) {
if (server == NULL || *server == NULL) return;
free(*server);
*server = NULL;
}
void server_listen(Server *server, void (*handler)(int file_descriptor)) {
log_message(LOG_LEVEL_INFO, "Start Listening on Port: %d",
+1 -1
View File
@@ -15,7 +15,7 @@ typedef struct Server {
Server *server_create(int port);
void server_listen(Server *server, void (*handler)(int file_descriptor));
void server_delete(Server *server);
void server_delete(Server **server);
typedef struct Client {
struct sockaddr_in address;
+1 -69
View File
@@ -80,77 +80,9 @@ static void test_chunk_operations() {
EXPECT_EQ_INT(memcmp(deserialized->items[0]->data->data, content1, len1), 0);
EXPECT_EQ_INT(memcmp(deserialized->items[1]->data->data, content2, len2), 0);
chunk_data_delete(serialized);
data_destroy(serialized);
chunk_destroy(deserialized);
// Test chunk_format layout (old format)
Data *formatted = chunk_format(chunk);
EXPECT_NOT_NULL(formatted);
unsigned long long expected_size =
(sizeof(int) + strlen(path1) + sizeof(int) + sizeof(unsigned long long) + len1) +
(sizeof(int) + strlen(path2) + sizeof(int) + sizeof(unsigned long long) + len2);
EXPECT_EQ_INT((int)formatted->size, (int)expected_size);
char *ptr = (char *)formatted->data;
// File 1
int p_len1;
memcpy(&p_len1, ptr, sizeof(int));
ptr += sizeof(int);
EXPECT_EQ_INT(p_len1, (int)strlen(path1));
char read_path1[256];
memcpy(read_path1, ptr, p_len1);
read_path1[p_len1] = '\0';
ptr += p_len1;
EXPECT_EQ_STR(read_path1, path1);
int meta_present1;
memcpy(&meta_present1, ptr, sizeof(int));
ptr += sizeof(int);
EXPECT_EQ_INT(meta_present1, 0);
unsigned long long d_len1;
memcpy(&d_len1, ptr, sizeof(unsigned long long));
ptr += sizeof(unsigned long long);
EXPECT_EQ_INT((int)d_len1, (int)len1);
char read_content1[256];
memcpy(read_content1, ptr, d_len1);
read_content1[d_len1] = '\0';
ptr += d_len1;
EXPECT_EQ_STR(read_content1, content1);
// File 2
int p_len2;
memcpy(&p_len2, ptr, sizeof(int));
ptr += sizeof(int);
EXPECT_EQ_INT(p_len2, (int)strlen(path2));
char read_path2[256];
memcpy(read_path2, ptr, p_len2);
read_path2[p_len2] = '\0';
ptr += p_len2;
EXPECT_EQ_STR(read_path2, path2);
int meta_present2;
memcpy(&meta_present2, ptr, sizeof(int));
ptr += sizeof(int);
EXPECT_EQ_INT(meta_present2, 0);
unsigned long long d_len2;
memcpy(&d_len2, ptr, sizeof(unsigned long long));
ptr += sizeof(unsigned long long);
EXPECT_EQ_INT((int)d_len2, (int)len2);
char read_content2[256];
memcpy(read_content2, ptr, d_len2);
read_content2[d_len2] = '\0';
ptr += d_len2;
EXPECT_EQ_STR(read_content2, content2);
chunk_data_delete(formatted);
chunk_destroy(chunk);
unlink(path1);
+28 -3
View File
@@ -26,12 +26,35 @@ static void test_config_lifecycle() {
static void test_config_ssh_dest() {
Config *cfg = config_create(str_dup("1.0"), str_dup("/src"), str_dup("user@host:/dst"),
true, false, false, false, false, 1, 4, false);
cfg->transport = TRANSPORT_SSH;
cfg->ssh_destination = str_dup("user@host:/dst");
EXPECT_NOT_NULL(cfg);
EXPECT_EQ_INT(cfg->transport, TRANSPORT_TCP);
EXPECT_NULL(cfg->ssh_destination);
EXPECT_EQ_STR(cfg->receive_root_directory, "user@host:/dst");
config_parse_ssh_dest(cfg);
EXPECT_EQ_INT(cfg->transport, TRANSPORT_SSH);
EXPECT_EQ_STR(cfg->ssh_destination, "user@host:/dst");
EXPECT_EQ_STR(cfg->receive_root_directory, "user@host:/dst");
EXPECT_EQ_STR(cfg->receive_root_directory, "/dst");
config_delete(cfg);
}
static void test_config_ssh_dest_local_path() {
Config *cfg = config_create(str_dup("1.0"), str_dup("/src"), str_dup("/local/path"),
true, false, false, false, false, 1, 4, false);
config_parse_ssh_dest(cfg);
EXPECT_EQ_INT(cfg->transport, TRANSPORT_TCP);
EXPECT_NULL(cfg->ssh_destination);
EXPECT_EQ_STR(cfg->receive_root_directory, "/local/path");
config_delete(cfg);
}
static void test_config_ssh_dest_no_user() {
Config *cfg = config_create(str_dup("1.0"), str_dup("/src"), str_dup("host:/remote"),
true, false, false, false, false, 1, 4, false);
config_parse_ssh_dest(cfg);
EXPECT_EQ_INT(cfg->transport, TRANSPORT_SSH);
EXPECT_EQ_STR(cfg->ssh_destination, "host:/remote");
EXPECT_EQ_STR(cfg->receive_root_directory, "/remote");
config_delete(cfg);
}
@@ -70,6 +93,8 @@ static void test_pipeline_receiver_lifecycle() {
void test_config() {
test_config_lifecycle();
test_config_ssh_dest();
test_config_ssh_dest_local_path();
test_config_ssh_dest_no_user();
test_pipeline_sender_lifecycle();
test_pipeline_receiver_lifecycle();
}