feat: add 8-bit output option
CI / lint (pull_request) Successful in 11s
CI / sanitizers (address) (pull_request) Successful in 37s
CI / sanitizers (undefined) (pull_request) Successful in 36s
CI / fuzz-build (pull_request) Successful in 16s
CI / coverage (pull_request) Successful in 33s
CI / build-and-test (pull_request) Successful in 1m15s
CI / valgrind (pull_request) Successful in 33s
CI / lint (pull_request) Successful in 11s
CI / sanitizers (address) (pull_request) Successful in 37s
CI / sanitizers (undefined) (pull_request) Successful in 36s
CI / fuzz-build (pull_request) Successful in 16s
CI / coverage (pull_request) Successful in 33s
CI / build-and-test (pull_request) Successful in 1m15s
CI / valgrind (pull_request) Successful in 33s
This commit is contained in:
@@ -68,6 +68,7 @@ static void config_set_defaults(Config* config) {
|
||||
config->debug_level = 0;
|
||||
config->list_only = false;
|
||||
config->human_readable = false;
|
||||
config->eight_bit_output = false;
|
||||
config->update = false;
|
||||
config->inplace = false;
|
||||
config->append = false;
|
||||
|
||||
@@ -74,6 +74,7 @@ typedef struct Config {
|
||||
int debug_level;
|
||||
bool list_only;
|
||||
bool human_readable;
|
||||
bool eight_bit_output;
|
||||
|
||||
// Issue #127: Transfer modes
|
||||
bool update;
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
static const char* log_level_strings[] = {"DEBUG", "INFO", "WARN", "ERROR"};
|
||||
static LogLevel current_log_level = LOG_LEVEL_WARNING;
|
||||
static FILE* log_fp = NULL;
|
||||
static bool eight_bit_output = false;
|
||||
|
||||
void set_log_level(LogLevel level) {
|
||||
current_log_level = level;
|
||||
@@ -17,6 +18,14 @@ void log_set_file(FILE* fp) {
|
||||
log_fp = fp;
|
||||
}
|
||||
|
||||
void log_set_8_bit_output(bool enabled) {
|
||||
eight_bit_output = enabled;
|
||||
}
|
||||
|
||||
bool log_get_8_bit_output(void) {
|
||||
return eight_bit_output;
|
||||
}
|
||||
|
||||
static inline void write_message(FILE* dest_io, LogLevel log_level, struct tm t, const char* format,
|
||||
va_list args) {
|
||||
fprintf(dest_io, "%04d-%02d-%02d %02d:%02d:%02d [%s]: ", t.tm_year + 1900, t.tm_mon + 1,
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define LOG_H
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef enum { LOG_LEVEL_DEBUG, LOG_LEVEL_INFO, LOG_LEVEL_WARNING, LOG_LEVEL_ERROR } LogLevel;
|
||||
|
||||
@@ -9,5 +10,7 @@ void log_message(LogLevel log_level, const char* message, ...);
|
||||
void log_perror(const char* context);
|
||||
void set_log_level(LogLevel level);
|
||||
void log_set_file(FILE* fp);
|
||||
void log_set_8_bit_output(bool enabled);
|
||||
bool log_get_8_bit_output(void);
|
||||
|
||||
#endif
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
#include "protocol.h"
|
||||
#include "log.h"
|
||||
#include "utils.h"
|
||||
#include <errno.h>
|
||||
#include <limits.h>
|
||||
#include <openssl/ssl.h>
|
||||
@@ -328,7 +329,9 @@ bool protocol_send_str(ProtocolSession* session, const char* data) {
|
||||
return false;
|
||||
if (!protocol_send_n_data(session, data, size))
|
||||
return false;
|
||||
log_message(LOG_LEVEL_DEBUG, "Send String: %s", data);
|
||||
char* escaped = output_escape(data, log_get_8_bit_output());
|
||||
log_message(LOG_LEVEL_DEBUG, "Send String: %s", escaped ? escaped : "<allocation failed>");
|
||||
free(escaped);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -356,7 +359,9 @@ char* protocol_receive_str(ProtocolSession* session) {
|
||||
}
|
||||
data[size] = '\0';
|
||||
session->total_allocated_bytes += size + 1;
|
||||
log_message(LOG_LEVEL_DEBUG, "Received String: %s", data);
|
||||
char* escaped = output_escape(data, log_get_8_bit_output());
|
||||
log_message(LOG_LEVEL_DEBUG, "Received String: %s", escaped ? escaped : "<allocation failed>");
|
||||
free(escaped);
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
+30
-1
@@ -1,6 +1,7 @@
|
||||
#include "utils.h"
|
||||
#include "array_list.h"
|
||||
#include "libgen.h"
|
||||
#include "log.h"
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@@ -132,6 +133,32 @@ char* str_dup(const char* string) {
|
||||
return new_string;
|
||||
}
|
||||
|
||||
char* output_escape(const char* string, bool eight_bit_output) {
|
||||
if (!string)
|
||||
return NULL;
|
||||
size_t length = strlen(string);
|
||||
if (length > (SIZE_MAX - 1) / 5)
|
||||
return NULL;
|
||||
char* escaped = malloc(length * 5 + 1);
|
||||
if (!escaped)
|
||||
return NULL;
|
||||
size_t out = 0;
|
||||
for (size_t i = 0; i < length; i++) {
|
||||
unsigned char byte = (unsigned char)string[i];
|
||||
if ((byte >= 32 && byte <= 126) || (eight_bit_output && byte >= 128)) {
|
||||
escaped[out++] = (char)byte;
|
||||
} else {
|
||||
escaped[out++] = '\\';
|
||||
escaped[out++] = '#';
|
||||
escaped[out++] = (char)('0' + ((byte >> 6) & 7));
|
||||
escaped[out++] = (char)('0' + ((byte >> 3) & 7));
|
||||
escaped[out++] = (char)('0' + (byte & 7));
|
||||
}
|
||||
}
|
||||
escaped[out] = '\0';
|
||||
return escaped;
|
||||
}
|
||||
|
||||
/* Match a glob pattern against a string. Supported wildcards:
|
||||
* ? matches any single character except '/'.
|
||||
* * matches any sequence of characters within one path component (no '/').
|
||||
@@ -274,7 +301,9 @@ static bool delete_extras_fd(int dirfd, const char* rel_path, ArrayList* manifes
|
||||
} else {
|
||||
(*deleted_count)++;
|
||||
}
|
||||
fprintf(stderr, " Deleted: %s\n", child_rel);
|
||||
char* escaped_path = output_escape(child_rel, log_get_8_bit_output());
|
||||
fprintf(stderr, " Deleted: %s\n", escaped_path ? escaped_path : "<allocation failed>");
|
||||
free(escaped_path);
|
||||
}
|
||||
}
|
||||
free(child_rel);
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
|
||||
bool mkdir_r(const char* path);
|
||||
char* str_dup(const char* string);
|
||||
char* output_escape(const char* string, bool eight_bit_output);
|
||||
char* path_cat(const char* path1, const char* path2);
|
||||
bool glob_match(const char* pattern, const char* str);
|
||||
bool delete_extras(const char* dest_root, ArrayList* manifest);
|
||||
|
||||
Reference in New Issue
Block a user