49 #include <arpa/inet.h> 55 #include "../include/libtrap/trap.h" 81 for (i = 0; i < config->
file_cnt; i++) {
82 free(config->
files[i]);
98 VERBOSE(
CL_ERROR,
"FILE IFC: attempt to destroy IFC that is probably not initialized.");
111 VERBOSE(
CL_ERROR,
"FILE IFC: attempt to terminate IFC that is probably not initialized.");
124 mode_t perm = S_IRWXU | S_IXGRP | S_IRGRP | S_IROTH | S_IXOTH;
125 const size_t len = strlen(path);
126 char _path[PATH_MAX];
129 if (len >
sizeof(_path) - 1) {
134 for (p = _path + 1; *p; p++) {
139 if (mkdir(_path, perm) != 0) {
140 if (errno != EEXIST) {
161 char *config_file = NULL;
165 ret = asprintf(&config_file,
"%s/trap-i%02"PRIu32
"-config.txt", path, idx);
167 VERBOSE(
CL_ERROR,
"FILE IFC: not enough memory, dump failed. (%s:%d)", __FILE__, __LINE__);
171 fd = fopen(config_file,
"w");
174 VERBOSE(
CL_ERROR,
"FILE IFC: unable to write to dump file. (%s:%d)", __FILE__, __LINE__);
198 uint8_t valid_suffix_present = 0;
225 if (config->
mode[0] ==
'a') {
227 if (sprintf(suffix,
".%05" PRIu16, config->
file_index) < 0) {
242 if (access(buf, F_OK) != 0) {
244 valid_suffix_present = 1;
252 if (sprintf(suffix,
".%05" PRIu16, config->
file_index) < 0) {
264 strncpy(config->
filename, buf, len);
287 VERBOSE(
CL_ERROR,
"FILE IFC[%"PRIu32
"]: unable to open file \"%s\" in mode \"%c\". Possible reasons: non-existing file, bad permission, file can not be opened in this mode.", c->
ifc_idx, c->
filename, c->
mode[0]);
313 uint16_t *m_head =
data;
314 uint32_t data_size = 0;
323 if (config->
fd == NULL) {
327 #ifdef ENABLE_NEGOTIATION 332 VERBOSE(
CL_VERBOSE_LIBRARY,
"FILE INPUT IFC[%"PRIu32
"] negotiation result: failed (unknown data format of the output interface).", config->ifc_idx);
337 config->neg_initialized = 1;
341 VERBOSE(
CL_VERBOSE_LIBRARY,
"FILE INPUT IFC[%"PRIu32
"] negotiation result: success (data specifier of the input interface is subset of the output interface data specifier).", config->ifc_idx);
342 config->neg_initialized = 1;
346 VERBOSE(
CL_VERBOSE_LIBRARY,
"FILE INPUT IFC[%"PRIu32
"] negotiation result: success (new data specifier of the output interface is subset of the old one; it was not first negotiation).", config->ifc_idx);
347 config->neg_initialized = 1;
351 VERBOSE(
CL_VERBOSE_LIBRARY,
"FILE INPUT IFC[%"PRIu32
"] negotiation result: failed (error while receiving hello message from output interface).", config->ifc_idx);
355 VERBOSE(
CL_VERBOSE_LIBRARY,
"FILE INPUT IFC[%"PRIu32
"] negotiation result: failed (data format or data specifier mismatch).", config->ifc_idx);
366 loaded = fread(&data_size,
sizeof(uint32_t), 1, config->
fd);
368 if (feof(config->
fd)) {
382 #ifdef ENABLE_NEGOTIATION 394 *size = ntohl(data_size);
396 loaded = fread(
data, 1, (*size), config->
fd);
397 if (loaded != (*size)) {
398 VERBOSE(
CL_ERROR,
"INPUT FILE IFC[%"PRIu32
"]: Read incorrect number of bytes from file: %s. Attempted to read %d bytes, but the actual count of bytes read was %zu.", config->
ifc_idx, config->
filename, (*size), loaded);
415 if (config->
fd != NULL) {
439 if (params == NULL) {
452 if (wordexp(params, &files_exp, 0) != 0) {
453 VERBOSE(
CL_ERROR,
"FILE INPUT IFC[%"PRIu32
"]: Unable to perform shell-like expansion of: %s", idx, params);
458 if (files_exp.we_wordc == 0) {
459 VERBOSE(
CL_ERROR,
"FILE INPUT IFC[%"PRIu32
"]: No files found for parameter: '%s'", idx, params);
464 priv->
file_cnt = files_exp.we_wordc;
465 priv->
files = (
char**) calloc(priv->
file_cnt,
sizeof(
char*));
468 wordfree(&files_exp);
472 for (i = 0; i < priv->
file_cnt; i++) {
473 name_length = strlen(files_exp.we_wordv[i]);
474 priv->
files[i] = (
char*) calloc(name_length + 1,
sizeof(
char));
475 if (!priv->
files[i]) {
476 for (j = i - 1; j >= 0; j --) {
477 free(priv->
files[j]);
482 wordfree(&files_exp);
486 strncpy(priv->
files[i], files_exp.we_wordv[i], name_length);
489 wordfree(&files_exp);
492 if (strlen(priv->
files[0]) > PATH_MAX - 1) {
493 VERBOSE(
CL_ERROR,
"FILE INPUT IFC[%"PRIu32
"]: Path and filename exceeds maximum size: %u.", idx, PATH_MAX - 1);
494 for (i = 0; i < priv->
file_cnt; i++) {
495 free(priv->
files[i]);
506 strcpy(priv->
mode,
"rb");
510 if (priv->
fd == NULL) {
511 VERBOSE(
CL_ERROR,
"INPUT FILE IFC[%"PRIu32
"]: unable to open file \"%s\". Possible reasons: non-existing file, bad permission.", idx, priv->
filename);
512 for (i = 0; i < priv->
file_cnt; i++) {
513 free(priv->
files[i]);
575 if (config->
fd == NULL) {
579 #ifdef ENABLE_NEGOTIATION 584 config->neg_initialized = 1;
587 VERBOSE(
CL_VERBOSE_LIBRARY,
"FILE OUTPUT IFC[%"PRIu32
"] negotiation result: failed (unknown data format of this output interface -> refuse client).", config->ifc_idx);
590 VERBOSE(
CL_VERBOSE_LIBRARY,
"FILE OUTPUT IFC[%"PRIu32
"] negotiation result: failed (error while sending hello message to input interface).", config->ifc_idx);
597 written = fwrite(
data, 1, size, config->
fd);
598 if (written != size) {
603 time_t current_time = time(NULL);
611 return trap_errorf(config->
ctx, status,
"FILE OUTPUT IFC[%"PRIu32
"]: Error during output file creation.", config->
ifc_idx);
617 return trap_errorf(config->
ctx, status,
"FILE OUTPUT IFC[%"PRIu32
"]: Error during output file opening.", config->
ifc_idx);
627 return trap_errorf(config->
ctx, status,
"FILE OUTPUT IFC[%"PRIu32
"]: Error during output file creation.", config->
ifc_idx);
633 return trap_errorf(config->
ctx, status,
"FILE OUTPUT IFC[%"PRIu32
"]: Error during output file opening.", config->
ifc_idx);
642 uint32_t header = htonl(buffer->
wr_index);
643 memcpy(buffer->
header, &header,
sizeof(header));
649 uint16_t *msize = (uint16_t *)(buffer->
data + buffer->
wr_index);
650 (*msize) = htons(size);
651 memcpy((
void *)(msize + 1),
data, size);
652 buffer->
wr_index += (size +
sizeof(size));
672 VERBOSE(
CL_ERROR,
"File IFC flush failed (file_write_buffer returned %i)", result);
688 static inline int file_send(
void *priv,
const void *
data, uint16_t size,
int timeout)
693 uint32_t needed_size = size +
sizeof(size);
695 uint8_t reinsert = 0;
704 if (free_bytes >= needed_size) {
769 const char *params_next = NULL;
770 wordexp_t exp_result;
775 if (params == NULL) {
788 priv->
buffer.
header = malloc(buffer_size +
sizeof(buffer_size));
798 strcpy(priv->
mode,
"wb");
801 length = strcspn(params,
":");
802 if (params[length] ==
':') {
803 params_next = params + length + 1;
807 dest = (
char*) calloc(length + 1,
sizeof(
char));
814 strncpy(dest, params, length);
822 if (wordexp(dest, &exp_result, 0) != 0) {
823 VERBOSE(
CL_ERROR,
"FILE OUTPUT IFC[%"PRIu32
"]: Unable to perform shell-like expansion of: %s", idx, dest);
827 wordfree(&exp_result);
833 wordfree(&exp_result);
842 while (params_next) {
843 length = strcspn(params_next,
":");
856 }
else if (length == 1 && params_next[0] ==
'a') {
860 if (params_next[length] ==
'\0') {
864 params_next = params_next + length + 1;
873 return trap_errorf(ctx, status,
"FILE OUTPUT IFC[%"PRIu32
"]: Error during output file creation.", idx);
881 return trap_errorf(ctx, status,
"FILE OUTPUT IFC[%"PRIu32
"]: Error during output file opening.", idx);
#define TIME_FORMAT_STRING_LEN
#define TRAP_E_OK
Success, no error.
int create_next_filename(file_private_t *config)
Create a new path and filename from the template created during interface initialization. New filename is stored in file_private_t->filename.
int32_t file_get_client_count(void *priv)
ifc_get_client_stats_json_func_t get_client_stats_json
Pointer to get_client_stats_json function.
char * file_send_ifc_get_id(void *priv)
#define NEG_RES_SENDER_FMT_SUBSET
If the data format of input and output interfaces is the same and new data specifier of the output in...
Internal functions and macros for libtrap Verbose and debug macros from libcommlbr.
int8_t file_get_client_stats_json(void *priv, json_t *client_stats_arr)
int _mkdir(const char *path)
Create path, recursive.
#define FILE_SIZE_SUFFIX_LEN
#define NEG_RES_FAILED
If receiving the data from output interface fails or sending the data to input interface fails...
ifc_get_id_func_t get_id
Pointer to get_id function.
int output_ifc_negotiation(void *ifc_priv_data, char ifc_type, uint32_t client_idx)
static void insert_into_buffer(file_buffer_t *buffer, const void *data, uint16_t size)
#define TRAP_E_TERMINATED
Interface was terminated during reading/writing.
void switch_file_wrapper(void *priv)
uint8_t file_recv_ifc_is_conn(void *priv)
uint32_t file_change_time
void file_terminate(void *priv)
Set interface state as terminated.
ifc_create_dump_func_t create_dump
Pointer to function for generating of dump.
int create_file_send_ifc(trap_ctx_priv_t *ctx, const char *params, trap_output_ifc_t *ifc, uint32_t idx)
Allocate and initiate file output interface. This function is called by TRAP library to initialize on...
#define TRAP_E_IO_ERROR
IO Error.
#define VERBOSE(level, format, args...)
static int trap_errorf(trap_ctx_priv_t *ctx, int err_num, const char *msg,...)
ifc_get_client_count_func_t get_client_count
Pointer to get_client_count function.
#define NEG_RES_CONT
If the data format and data specifier of input and output interface are the same (input interface can...
void file_destroy(void *priv)
Close file and free allocated memory.
ifc_disconn_clients_func_t disconn_clients
Pointer to disconnect_clients function.
char filename_tmplt[FILENAME_TEMPLATE_LEN]
#define TIME_FORMAT_STRING
char bufferswitch
Enable (1) or Disable (0) buffering, default is Enabled (1).
int create_file_recv_ifc(trap_ctx_priv_t *ctx, const char *params, trap_input_ifc_t *ifc, uint32_t idx)
Allocate and initiate file input interface. This function is called by TRAP library to initialize one...
uint32_t file_change_size
#define TRAP_E_NEGOTIATION_FAILED
Returned by trap_recv when negotiation of the output and input interfaces failed. ...
ifc_send_func_t send
Pointer to send function.
#define NEG_RES_FMT_UNKNOWN
If the output interface has not specified data format.
#define TRAP_E_FORMAT_MISMATCH
Returned by trap_recv when data format or data specifier of the output and input interfaces doesn't m...
static void finish_buffer(file_buffer_t *buffer)
#define NEG_RES_FMT_MISMATCH
If the data format or data specifier of input and output interfaces does not match.
int file_recv(void *priv, void *data, uint32_t *size, int timeout)
Read data from a file.
#define TRAP_E_MEMORY
Memory allocation error.
char * file_recv_ifc_get_id(void *priv)
#define NEG_RES_OK
Signaling success (hello message successfully sent to input interface)
ifc_destroy_func_t destroy
Pointer to destructor function.
int file_write_buffer(void *priv, const void *data, uint32_t size, int timeout)
Write data to a file. Data to write are expected as a trap_buffer_header_t structure, thus actual length of data to be written is determined from trap_buffer_header_t->data_length trap_buffer_header_t->data_length is expected to be in network byte order (little endian)
ifc_terminate_func_t terminate
Pointer to terminate function.
static void file_create_dump(void *priv, uint32_t idx, const char *path)
Create file dump with current configuration (for debugging)
static int trap_error(trap_ctx_priv_t *ctx, int err_num)
void file_flush(void *priv)
#define NEG_RES_RECEIVER_FMT_SUBSET
If the data format of input and output interfaces is the same and data specifier of the input interfa...
ifc_flush_func_t flush
Pointer to flush function.
#define TRAP_IFC_TYPE_FILE
trap_ifc_file (input&output part)
uint64_t * counter_send_buffer
int input_ifc_negotiation(void *ifc_priv_data, char ifc_type)
#define TRAP_E_NOT_INITIALIZED
TRAP library not initilized.
void * priv
Pointer to instance's private data.
trap_output_ifc_t * out_ifc_list
Interface of TRAP interfaces.
static int file_send(void *priv, const void *data, uint16_t size, int timeout)
Store message into buffer. Write buffer into file if full. If buffering is disabled, the message is sent to the output interface immediately.
int switch_file(file_private_t *c)
Close previous file, open next file (name taken in file_private_t->filename). Negotiation must be per...
#define TRAP_E_BADPARAMS
Bad parameters passed to interface initializer.
#define TRAP_IFC_MESSAGEQ_SIZE
size of message queue used for buffering