From a19917522862f26bc711fd8271940906284ff55d Mon Sep 17 00:00:00 2001 From: Robbie Harwood Date: Tue, 10 Apr 2018 15:55:41 -0400 Subject: [PATCH] Merge duplicate subsections in profile library Modify profile_add_node() to return the existing node, rather than making a new one, when adding subsection configuration. This fixes an issue where the first instance of a subsection will hide the second instance entirely. In particular, it was previously impossible to split realm-specific configuration across multiple config files. [ghudson@mit.edu: adjusted style, added test case] (cherry picked from commit efab9fa5a6d23c486467264e20b58bf5a9c60f0c) ticket: 7863 version_fixed: 1.16.1 (cherry picked from commit 98d0061c8083af960438ad1ac088f60497694a68) --- src/util/profile/prof_test1 | 22 ++++++++++++++++++++++ src/util/profile/prof_tree.c | 15 +++++++++++---- src/util/profile/test.ini | 6 ++++++ 3 files changed, 39 insertions(+), 4 deletions(-) diff --git a/src/util/profile/prof_test1 b/src/util/profile/prof_test1 index 7e30fc12f..7d13c9389 100644 --- a/src/util/profile/prof_test1 +++ b/src/util/profile/prof_test1 @@ -341,6 +341,27 @@ proc test9 {} { puts "OK: test9: profile_flush_to_file with no changes" } +proc test10 {} { + global wd verbose + + # Regression test for #7863: multiply-specified subsections should + # be merged. + set p [profile_init_path $wd/test2.ini] + set x [profile_get_values $p {{test section 2} child_section2 child}] + if $verbose { puts "Read $x from profile" } + if ![string equal $x "slick harry {john\tb } ron"] { + puts stderr "Error: test10: Did not get expected merged children." + exit 1 + } + + set x [profile_get_string $p {test section 2} child_section2 chores] + if $verbose { puts "Read $x from profile" } + if ![string equal $x "cleaning"] { + puts stderr "Error: test10: Did not find expected chores." + exit 1 + } +} + test1 test2 test3 @@ -350,5 +371,6 @@ test6 test7 test8 test9 +test10 exit 0 diff --git a/src/util/profile/prof_tree.c b/src/util/profile/prof_tree.c index 081f688e4..38aadc4e5 100644 --- a/src/util/profile/prof_tree.c +++ b/src/util/profile/prof_tree.c @@ -9,7 +9,7 @@ * * Each node may represent either a relation or a section header. * - * A section header must have its value field set to 0, and may a one + * A section header must have its value field be null, and may have one * or more child nodes, pointed to by first_child. * * A relation has as its value a pointer to allocated memory @@ -159,15 +159,22 @@ errcode_t profile_add_node(struct profile_node *section, const char *name, return PROF_ADD_NOT_SECTION; /* - * Find the place to insert the new node. We look for the - * place *after* the last match of the node name, since + * Find the place to insert the new node. If we are adding a subsection + * and already have a subsection with that name, merge them. Otherwise, + * we look for the place *after* the last match of the node name, since * order matters. */ for (p=section->first_child, last = 0; p; last = p, p = p->next) { int cmp; cmp = strcmp(p->name, name); - if (cmp > 0) + if (cmp > 0) { break; + } else if (value == NULL && cmp == 0 && + p->value == NULL && p->deleted != 1) { + /* Found duplicate subsection, so don't make a new one. */ + *ret_node = p; + return 0; + } } retval = profile_create_node(name, value, &new); if (retval) diff --git a/src/util/profile/test.ini b/src/util/profile/test.ini index 23ca89677..6622df108 100644 --- a/src/util/profile/test.ini +++ b/src/util/profile/test.ini @@ -10,6 +10,12 @@ this is a comment. Everything up to the first square brace is ignored. } child_section2 = foo +[test section 2] + child_section2 = { + child = ron + chores = cleaning + } + [realms] ATHENA.MIT.EDU = { server = KERBEROS.MIT.EDU:88