#include <freeradius-devel/util/print.h>
#include <freeradius-devel/util/sbuff.h>
#include <freeradius-devel/util/strerror.h>
+#include <freeradius-devel/util/syserror.h>
#include <freeradius-devel/util/talloc.h>
#include <freeradius-devel/util/thread_local.h>
* relative to content.
*/
update_ptr(buff, max_shift, sbuff_i->p);
-
+ update_ptr(buff, max_shift, sbuff_i->end);
sbuff_i->shifted += max_shift;
for (m_i = sbuff_i->m; m_i; m_i = m_i->next) update_ptr(buff, max_shift, m_i->p);
return max_shift;
}
+/** Refresh the buffer with more data from the file
+ *
+ */
+size_t fr_sbuff_extend_file(fr_sbuff_t *sbuff, size_t extension)
+{
+ size_t shifted, read, available;
+ fr_sbuff_uctx_file_t *fctx = sbuff->uctx;
+
+ if (extension == SIZE_MAX) extension = 0;
+
+ if (fr_sbuff_used(sbuff)) {
+ /*
+ * Try and shift as much as we can out
+ * of the buffer to make space.
+ *
+ * Note: p and markers are constraints here.
+ */
+ shifted = fr_sbuff_shift(sbuff, fr_sbuff_used(sbuff));
+ }
+
+ available = fctx->buff_end - sbuff->end;
+ if (available < extension) {
+ fr_strerror_printf("Can't satisfy extension request for %zu bytes", extension);
+ return 0; /* There's no way we could satisfy the extension request */
+ }
+
+ read = fread(sbuff->end, 1, available, fctx->file);
+ sbuff->end += read; /* Advance end, which increases fr_sbuff_remaining() */
+
+ /** Check for errors
+ */
+ if (read < available) {
+ if (!feof(fctx->file)) { /* It's a real error */
+ fr_strerror_printf("Error extending buffer: %s", fr_syserror(ferror(fctx->file)));
+ return 0;
+ }
+ }
+
+ return read;
+}
+
/** Reallocate the current buffer
*
* @param[in] sbuff to be extended.
#include <limits.h>
#include <stdbool.h>
#include <stdint.h>
+#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <talloc.h>
size_t max; //!< Maximum size of the buffer.
} fr_sbuff_uctx_talloc_t;
+/** File sbuff extension structure
+ *
+ * Holds the data necessary for creating dynamically
+ * extensible file buffers.
+ */
+typedef struct {
+ FILE *file; //!< FILE * we're reading from.
+ char *buff_end; //!< The true end of the buffer.
+ size_t max; //!< Maximum number of bytes to read.
+} fr_sbuff_uctx_file_t;
+
/** Terminal element with pre-calculated lengths
*
*/
size_t fr_sbuff_shift(fr_sbuff_t *sbuff, size_t shift);
+size_t fr_sbuff_extend_file(fr_sbuff_t *sbuff, size_t extension);
+
size_t fr_sbuff_extend_talloc(fr_sbuff_t *sbuff, size_t extenison);
int fr_sbuff_trim_talloc(fr_sbuff_t *sbuff, size_t len);
char const * : _fr_sbuff_init(_out, _start, (char const *)(_len_or_end), true) \
)
+/** Initialise a special sbuff which automatically reads in more data as the buffer is exhausted
+ *
+ * @param[out] sbuff to initialise.
+ * @param[out] fctx to initialise. Must have a lifetime >= to the sbuff.
+ * @param[in] buff Temporary buffer to use for storing file contents.
+ * @param[in] len Length of the temporary buffer.
+ * @param[in] max The maximum length of data to read from the file.
+ * @return
+ * - The passed sbuff on success.
+ * - NULL on failure.
+ */
+static inline fr_sbuff_t *fr_sbuff_init_file(fr_sbuff_t *sbuff, fr_sbuff_uctx_file_t *fctx,
+ char *buff, size_t len, FILE *file, size_t max)
+{
+ *fctx = (fr_sbuff_uctx_file_t){
+ .file = file,
+ .max = max,
+ .buff_end = buff + len //!< Store the real end
+ };
+
+ *sbuff = (fr_sbuff_t){
+ .buff = buff,
+ .start = buff,
+ .p = buff,
+ .end = buff, //!< Starts with 0 bytes available
+ .extend = fr_sbuff_extend_file,
+ .uctx = fctx
+ };
+
+ return sbuff;
+}
+
/** Initialise a special sbuff which automatically extends as additional data is written
*
* @param[in] ctx to allocate buffer in.