23RCSID(
"$Id: b0fb41a3602d804f61750a0b09fa1b38a6716d15 $")
25#include <freeradius-devel/util/iovec.h>
77static inline CC_HINT(always_inline)
84 entry->request = NULL;
109static inline CC_HINT(always_inline)
114 for (entry = start_entry; entry <
file->entry_p; entry++) {
116 entry->
error = error;
126 int ret, written, fd = -1;
128 size_t len = 0, header_len = 0;
129 off_t offset, file_size;
131 struct stat stat_buf;
132 struct iovec to_write[3];
133 struct iovec *to_write_p = to_write;
144 with_delim = (
inst->delimiter_len > 0);
154 if (
inst->file.group_str && (chown(
file->filename, -1,
inst->file.group) == -1)) {
165 to_write_p->iov_base =
UNCONST(
char *,
file->log_header->vb_strvalue);
166 header_len = to_write_p->iov_len =
file->log_header->vb_length;
170 to_write_p->iov_base =
UNCONST(
char *,
inst->delimiter);
171 header_len += to_write_p->iov_len =
inst->delimiter_len;
180 if (fstat(fd, &stat_buf) < 0) {
184 file_size = stat_buf.st_size;
188 written = ret - header_len;
191 if (ret < (
ssize_t)(header_len)) {
192 ret = ftruncate(fd, 0);
194 ERROR(
"Failed truncating file \"%s\" after partial header write - %s",
198 PERROR(
"Failed writing header to \"%s\"",
file->filename);
205 if (fstat(fd, &stat_buf) < 0) {
210 written = stat_buf.st_size - file_size - header_len;
212 if ((errno == ENOSPC) && (written > 0)) {
213 ERROR(
"No space left on device when writing to \"%s\". Not all data was written",
227 len += entry->data_len;
229 if (len > (
size_t)written) {
231 ROPTIONAL(
RWARN,
WARN,
"Buffered log write failed. Expected %zu bytes, but only %zu bytes were written", len, (
size_t)written);
232 ret = ftruncate(fd, offset + (len - entry->data_len + header_len));
234 ERROR(
"Failed truncating file \"%s\" after partial write - %s",
253 PERROR(
"Failed closing file %s",
file->filename);
272 struct iovec *vector_p,
size_t vector_len)
282 path = call_env->
filename->vb_strvalue;
289 talloc_set_name_const(
file,
"rlm_linelog_file_t");
291 file->filename = talloc_strdup(
file, path);
294 file->thread_inst = thread;
297 RPERROR(
"Failed to copy log header for buffered log file %pV", call_env->
filename);
304 file->entry_last =
file->entry +
inst->file.buffer_count;
333 file->entry_p->failed =
true;
337 *entry_p =
file->entry_p;
342 RWARN(
"Failed adding timer to write logs for %pV", call_env->
filename);
346 file->entry_p->data_len = ret;
349 if (
file->entry_p ==
file->entry_last) {
unlang_action_t
Returned by unlang_op_t calls, determine the next action of the interpreter.
@ UNLANG_ACTION_EXECUTE_NEXT
Execute the next unlang_t.
@ UNLANG_ACTION_FAIL
Encountered an unexpected error.
#define UNCONST(_type, _ptr)
Remove const qualification from a pointer.
#define CMP(_a, _b)
Same as CMP_PREFER_SMALLER use when you don't really care about ordering, you just want an ordering.
int fr_dbuff_reset_talloc(fr_dbuff_t *dbuff)
Reset a talloced buffer to its initial length, clearing any data stored.
#define fr_dbuff_used(_dbuff_or_marker)
Return the number of bytes remaining between the start of the dbuff or marker and the current positio...
#define fr_dbuff_start(_dbuff_or_marker)
Return the 'start' position of a dbuff or marker.
static fr_dbuff_t * fr_dbuff_init_talloc(TALLOC_CTX *ctx, fr_dbuff_t *dbuff, fr_dbuff_uctx_talloc_t *tctx, size_t init, size_t max)
Initialise a special dbuff which automatically extends as additional data is written.
static int fr_dcursor_insert(fr_dcursor_t *cursor, void *v)
Insert directly after the current item.
int exfile_open(exfile_t *ef, char const *filename, mode_t permissions, int flags, off_t *offset)
Open a new log file, or maybe an existing one.
int exfile_close(exfile_t *ef, int fd)
Close the log file.
uint32_t fr_hash_case_string(char const *p)
Hash a C string, converting all chars to lowercase.
bool fr_hash_table_insert(fr_hash_table_t *ht, void const *data)
Insert data into a hash table.
void * fr_hash_table_find_by_key(fr_hash_table_t *ht, uint32_t key, void const *data)
Hash table lookup with pre-computed key.
uint32_t fr_hash_string(char const *p)
bool fr_hash_table_delete(fr_hash_table_t *ht, void const *data)
Remove and free data (if a free function was specified)
#define fr_hash_table_alloc(_ctx, _hash_node, _cmp_node, _free_node)
void unlang_interpret_mark_runnable(request_t *request)
Mark a request as resumable.
bool unlang_interpret_is_resumable(request_t *request)
Check if a request as resumable.
ssize_t fr_writev(int fd, struct iovec vector[], int iovcnt, fr_time_delta_t timeout)
Write out a vector to a file descriptor.
fr_slen_t fr_concatv(fr_dbuff_t *out, struct iovec vector[], int iovcnt)
Concatenate an iovec into a dbuff.
#define ROPTIONAL(_l_request, _l_global, _fmt,...)
Use different logging functions depending on whether request is NULL or not.
@ FR_TYPE_SIZE
Unsigned integer capable of representing any memory address on the local system.
module_instance_t const * mi
Instance of the module being instantiated.
void * thread
Thread specific instance data.
void * rctx
Resume ctx that a module previously set.
Temporary structure to hold arguments for module calls.
linelog_buffer_action_t file_enqueue_write(rlm_linelog_file_entry_t **entry_p, module_ctx_t const *mctx, linelog_call_env_t const *call_env, request_t *request, struct iovec *vector_p, size_t vector_len)
void file_batching_mod_handle_signal(module_ctx_t const *mctx, request_t *request, fr_signal_t action)
static uint32_t filename_hash(void const *data)
void file_thread_init(rlm_linelog_thread_t *thread, fr_timer_list_t *tl)
void file_batching_xlat_handle_signal(xlat_ctx_t const *xctx, request_t *request, fr_signal_t action)
unlang_action_t file_batching_mod_resume(UNUSED unlang_result_t *p_result, module_ctx_t const *mctx, request_t *request)
static int8_t filename_cmp(void const *one, void const *two)
static void _batching_handle_timeout(UNUSED fr_timer_list_t *tl, UNUSED fr_time_t now, void *uctx)
static void _batching_cleanup_timer(UNUSED fr_timer_list_t *tl, UNUSED fr_time_t now, void *uctx)
static int _file_free(rlm_linelog_file_t *file)
static void _batch_write(rlm_linelog_file_t *file)
static void batching_mark_entries_failed(rlm_linelog_file_t *file, rlm_linelog_file_entry_t *start_entry, int error)
static void _batching_handle_signal(NDEBUG_UNUSED request_t *request, NDEBUG_UNUSED fr_signal_t action, rlm_linelog_file_entry_t *entry)
xlat_action_t file_batching_xlat_resume(TALLOC_CTX *ctx, fr_dcursor_t *out, xlat_ctx_t const *xctx, request_t *request, UNUSED fr_value_box_list_t *in)
char const * filename
Talloced filename string.
fr_timer_list_t * tl
Timer list for this thread.
request_t * request
The request that created the data.
fr_hash_table_t * file_table
Hash table of files.
size_t data_len
How much data this entry holds in the sbuff.
int error
Error code if the write failed.
@ LINELOG_BUFFER_WRITE_YIELD
Writing buffered data yielded.
@ LINELOG_BUFFER_WRITE_DONE
Writing buffered data completed.
@ LINELOG_BUFFER_WRITE_FAIL
Writing buffered data failed.
linelog module thread specific structure
fr_value_box_t * log_head
Header to add to each new log file.
fr_value_box_t * filename
File name, if output is to a file.
void * data
Module's instance data.
fr_signal_t
Signals that can be generated/processed by request signal handlers.
@ FR_SIGNAL_CANCEL
Request has been cancelled.
eap_aka_sim_process_conf_t * inst
char const * fr_syserror(int num)
Guaranteed to be thread-safe version of strerror.
#define talloc_get_type_abort_const
static fr_time_delta_t fr_time_delta_from_sec(int64_t sec)
#define fr_time_delta_wrap(_time)
#define fr_time_delta_gt(_a, _b)
#define FR_TIMER_DISARM(_ev)
static bool fr_timer_armed(fr_timer_t *ev)
@ XLAT_ACTION_FAIL
An xlat function failed.
@ XLAT_ACTION_DONE
We're done evaluating this level of nesting.
#define fr_type_is_null(_x)
int fr_value_box_copy(TALLOC_CTX *ctx, fr_value_box_t *dst, const fr_value_box_t *src)
Copy value data verbatim duplicating any buffers.
#define fr_value_box_alloc(_ctx, _type, _enumv)
Allocate a value box of a specific type.
#define fr_value_box_alloc_null(_ctx)
Allocate a value box for later use with a value assignment function.
static size_t char ** out
void * rctx
Resume context.