This will be used later to record the files attributes were defined in, with buffer lifetimes that are equal to the attribute lifetimes
char const *dependent; //!< File holding the reference.
} fr_dict_dependent_t;
+/** Entry in the filename list of files associated with this dictionary
+ *
+ * Mainly used for debugging.
+ */
+typedef struct {
+ fr_dlist_t entry; //!< Entry in the list of filenames.
+
+ char *filename; //!< Name of the file the dictionary was loaded on.
+} fr_dict_filename_t;
+
/** Vendors and attribute names
*
* It's very likely that the same vendors will operate in multiple
struct fr_dict_s {
fr_dict_gctx_t *gctx; //!< Global dictionary context this dictionary
///< was allocated in.
+
+ fr_dlist_head_t filenames; //!< Files that this dictionary was loaded from.
+
bool read_only; //!< If true, disallow modifications.
bool in_protocol_by_name; //!< Whether the dictionary has been inserted into the
return 0;
}
+/** Maintain a linked list of filenames which we've seen loading this dictionary
+ *
+ * This is used for debug messages, so we have a copy of the original file path
+ * that we can reference from fr_dict_attr_t without having the memory bloat of
+ * assigning a buffer to every attribute.
+ */
+static inline int dict_filename_add(char **filename_out, fr_dict_t *dict, char const *filename)
+{
+ fr_dict_filename_t *file;
+
+ file = talloc_zero(dict, fr_dict_filename_t);
+ if (unlikely(file == NULL)) {
+ oom:
+ fr_strerror_const("Out of memory");
+ return -1;
+ }
+ *filename_out = file->filename = talloc_typed_strdup(dict, filename);
+ if (unlikely(*filename_out == NULL)) goto oom;
+
+ fr_dlist_insert_tail(&dict->filenames, file);
+
+ return 0;
+}
+
/** Parse a dictionary file
*
* @param[in] ctx Contains the current state of the dictionary parser.
}
}
- ctx->stack[ctx->stack_depth].filename = fn;
+ /*
+ * Copy the filename into the dictionary and add it to the ctx
+ *
+ * This string is safe to assign to the filename pointer in
+ * any attributes added beneath the dictionary.
+ */
+ if (unlikely(dict_filename_add(&ctx->stack[ctx->stack_depth].filename, ctx->dict, fn) < 0)) return -1;
if ((fp = fopen(fn, "r")) == NULL) {
if (!src_file) {
#include <freeradius-devel/util/dict.h>
#include <freeradius-devel/util/dict_ext_priv.h>
#include <freeradius-devel/util/dict_fixup_priv.h>
+#include <freeradius-devel/util/dlist.h>
#include <freeradius-devel/util/proto.h>
#include <freeradius-devel/util/rand.h>
#include <freeradius-devel/util/sbuff.h>
dict->gctx = dict_gctx; /* Record which global context this was allocated in */
talloc_set_destructor(dict, _dict_free);
+ /*
+ * A list of all the files that constitute this dictionary
+ */
+ fr_dlist_talloc_init(&dict->filenames, fr_dict_filename_t, entry);
+
/*
* Pre-Allocate pool memory for rapid startup
* As that's the working memory required during