Ensure that the directory name always ends with /
[freeradius.git] / src / lib / dict.c
index ff99bfe..a3ea796 100644 (file)
@@ -851,10 +851,10 @@ int dict_addattr(const char *name, int attr, unsigned int vendor, int type,
        if (n->type == PW_TYPE_COMBO_IP) {
                DICT_ATTR *v4, *v6;
 
-               v4 = malloc(sizeof(*v4));
+               v4 = fr_pool_alloc(sizeof(*v4));
                if (!v4) goto oom;
 
-               v6 = malloc(sizeof(*v6));
+               v6 = fr_pool_alloc(sizeof(*v6));
                if (!v6) {
                        free(v4);
                        goto oom;
@@ -1096,7 +1096,7 @@ int dict_str2oid(const char *ptr, unsigned int *pvalue, unsigned int *pvendor,
 {
        const char *p;
        unsigned int value;
-       const DICT_ATTR *da;
+       const DICT_ATTR *da = NULL;
 
        if (tlv_depth > fr_attr_max_tlv) {
                fr_strerror_printf("Too many sub-attributes");
@@ -1175,7 +1175,7 @@ int dict_str2oid(const char *ptr, unsigned int *pvalue, unsigned int *pvendor,
                return -1;
        }
 
-       if (!*pvendor && (tlv_depth == 1) &&
+       if (!*pvendor && (tlv_depth == 1) && da &&
            (da->flags.has_tlv || da->flags.extended)) {
 
 
@@ -1378,7 +1378,6 @@ static int process_attribute(const char* fn, const int line,
                                fr_strerror_printf("dict_init: %s[%d]: Attributes of type \"extended\" MUST be RFC attributes with value >= 241.", fn, line);
                                return -1;
                        }
-                       type = PW_TYPE_OCTETS;
                        flags.extended = 1;
                        break;
 
@@ -1387,13 +1386,11 @@ static int process_attribute(const char* fn, const int line,
                                fr_strerror_printf("dict_init: %s[%d]: Attributes of type \"long-extended\" MUST be RFC attributes with value >= 241.", fn, line);
                                return -1;
                        }
-                       type = PW_TYPE_OCTETS;
                        flags.extended = 1;
                        flags.long_extended = 1;
                        break;
 
                case PW_TYPE_EVS:
-                       type = PW_TYPE_OCTETS;
                        flags.extended = 1;
                        flags.evs = 1;
                        if (value != PW_VENDOR_SPECIFIC) {
@@ -1879,11 +1876,11 @@ int str2argv(char *str, char **argv, int max_argc)
 /*
  *     Initialize the dictionary.
  */
-static int my_dict_init(const char *dir, const char *fn,
+static int my_dict_init(const char *parent, const char *filename,
                        const char *src_file, int src_line)
 {
        FILE    *fp;
-       char    dirtmp[256];
+       char    dir[256], fn[256];
        char    buf[256];
        char    *p;
        int     line = 0;
@@ -1900,23 +1897,51 @@ static int my_dict_init(const char *dir, const char *fn,
        block_tlv[2] = NULL;
        block_tlv[3] = NULL;
 
-       if (strlen(fn) >= sizeof(dirtmp) / 2 ||
-           strlen(dir) >= sizeof(dirtmp) / 2) {
+       if ((strlen(parent) + 3 + strlen(filename)) > sizeof(dir)) {
                fr_strerror_printf("dict_init: filename name too long");
                return -1;
        }
 
        /*
-        *      First see if fn is relative to dir. If so, create
-        *      new filename. If not, remember the absolute dir.
+        *      If it's an absolute dir, forget the parent dir,
+        *      and remember the new one.
+        *
+        *      If it's a relative dir, tack on the current filename
+        *      to the parent dir.  And use that.
         */
-       if ((p = strrchr(fn, FR_DIR_SEP)) != NULL) {
-               strcpy(dirtmp, fn);
-               dirtmp[p - fn] = 0;
-               dir = dirtmp;
-       } else if (dir && dir[0] && strcmp(dir, ".") != 0) {
-               snprintf(dirtmp, sizeof(dirtmp), "%s/%s", dir, fn);
-               fn = dirtmp;
+       if (!FR_DIR_IS_RELATIVE(filename)) {
+               strlcpy(dir, filename, sizeof(dir));
+               p = strrchr(dir, FR_DIR_SEP);
+               if (p) {
+                       p[1] = '\0';
+               } else {
+                       strlcat(dir, "/", sizeof(dir));
+               }
+
+               strlcpy(fn, filename, sizeof(fn));
+       } else {
+               strlcpy(dir, parent, sizeof(dir));
+               p = strrchr(dir, FR_DIR_SEP);
+               if (p) {
+                       if (p[1]) strlcat(dir, "/", sizeof(dir));
+               } else {
+                       strlcat(dir, "/", sizeof(dir));
+               }
+               strlcat(dir, filename, sizeof(dir));
+               p = strrchr(dir, FR_DIR_SEP);
+               if (p) {
+                       p[1] = '\0';
+               } else {
+                       strlcat(dir, "/", sizeof(dir));
+               }
+
+               p = strrchr(filename, FR_DIR_SEP);
+               if (p) {
+                       snprintf(fn, sizeof(fn), "%s%s", dir, p);
+               } else {
+                       snprintf(fn, sizeof(fn), "%s%s", dir, filename);
+               }
+
        }
 
        if ((fp = fopen(fn, "r")) == NULL) {
@@ -2452,6 +2477,8 @@ void dict_attr_free(DICT_ATTR const **da)
 {
        DICT_ATTR **tmp;
        
+       if (!da || !*da) return;
+       
        /* Don't free real DAs */
        if (!(*da)->flags.is_unknown) {
                return;
@@ -2471,6 +2498,8 @@ void dict_attr_free(DICT_ATTR const **da)
  * If the attr is known, a pointer to the da will be returned.
  *
  * @param da to copy.
+ * @param vp_free if TRUE, da will be freed at the same time as the
+ *     VALUE_PAIR which contains it.
  * @return return a copy of the da.
  */
 const DICT_ATTR *dict_attr_copy(const DICT_ATTR *da, int vp_free)
@@ -2801,7 +2830,7 @@ const DICT_ATTR *dict_attrbyvalue(unsigned int attr, unsigned int vendor)
  * @return The attribute, or NULL if not found
  */
 const DICT_ATTR *dict_attrbytype(unsigned int attr, unsigned int vendor,
-                          PW_TYPE type)
+                                PW_TYPE type)
 {
        DICT_ATTR dattr;
 
@@ -2812,7 +2841,6 @@ const DICT_ATTR *dict_attrbytype(unsigned int attr, unsigned int vendor,
        return fr_hash_table_finddata(attributes_combo, &dattr);
 }
 
-
 /**
  * @brief Using a parent and attr/vendor, find a child attr/vendor
  */