Add -sudo option to ini setting options

Add a -sudo option to allow these functions to operate on root-owned
files.  Test-case is updated, but not enabled by default as we can't
expect test-runner to have sudo access.

Change-Id: I134c3397314c7d9395996eb6c825ecb7e7fdfc69
diff --git a/inc/ini-config b/inc/ini-config
index 8e7c018..d23f474 100644
--- a/inc/ini-config
+++ b/inc/ini-config
@@ -15,30 +15,40 @@
 # ================
 
 # Append a new option in an ini file without replacing the old value
-# iniadd config-file section option value1 value2 value3 ...
+# iniadd [-sudo] config-file section option value1 value2 value3 ...
 function iniadd {
     local xtrace=$(set +o | grep xtrace)
     set +o xtrace
+    local sudo=""
+    if [ $1 == "-sudo" ]; then
+        sudo="-sudo "
+        shift
+    fi
     local file=$1
     local section=$2
     local option=$3
     shift 3
 
     local values="$(iniget_multiline $file $section $option) $@"
-    iniset_multiline $file $section $option $values
+    iniset_multiline $sudo $file $section $option $values
     $xtrace
 }
 
 # Comment an option in an INI file
-# inicomment config-file section option
+# inicomment [-sudo] config-file section option
 function inicomment {
     local xtrace=$(set +o | grep xtrace)
     set +o xtrace
+    local sudo=""
+    if [ $1 == "-sudo" ]; then
+        sudo="sudo "
+        shift
+    fi
     local file=$1
     local section=$2
     local option=$3
 
-    sed -i -e "/^\[$section\]/,/^\[.*\]/ s|^\($option[ \t]*=.*$\)|#\1|" "$file"
+    $sudo sed -i -e "/^\[$section\]/,/^\[.*\]/ s|^\($option[ \t]*=.*$\)|#\1|" "$file"
     $xtrace
 }
 
@@ -95,10 +105,15 @@
 # in the argument list. Doing that will cause incorrect configuration
 # if spaces are used in the config values.
 #
-# iniadd_literal config-file section option value
+# iniadd_literal [-sudo] config-file section option value
 function iniadd_literal {
     local xtrace=$(set +o | grep xtrace)
     set +o xtrace
+    local sudo=""
+    if [ $1 == "-sudo" ]; then
+        sudo="sudo "
+        shift
+    fi
     local file=$1
     local section=$2
     local option=$3
@@ -110,7 +125,7 @@
     fi
 
     # Add it
-    sed -i -e "/^\[$section\]/ a\\
+    $sudo sed -i -e "/^\[$section\]/ a\\
 $option = $value
 " "$file"
 
@@ -118,10 +133,15 @@
 }
 
 # Remove an option from an INI file
-# inidelete config-file section option
+# inidelete [-sudo] config-file section option
 function inidelete {
     local xtrace=$(set +o | grep xtrace)
     set +o xtrace
+    local sudo=""
+    if [ $1 == "-sudo" ]; then
+        sudo="sudo "
+        shift
+    fi
     local file=$1
     local section=$2
     local option=$3
@@ -132,16 +152,21 @@
     fi
 
     # Remove old values
-    sed -i -e "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ d; }" "$file"
+    $sudo sed -i -e "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ d; }" "$file"
 
     $xtrace
 }
 
 # Set an option in an INI file
-# iniset config-file section option value
+# iniset [-sudo] config-file section option value
 function iniset {
     local xtrace=$(set +o | grep xtrace)
     set +o xtrace
+    local sudo=""
+    if [ $1 == "-sudo" ]; then
+        sudo="sudo "
+        shift
+    fi
     local file=$1
     local section=$2
     local option=$3
@@ -154,26 +179,31 @@
 
     if ! grep -q "^\[$section\]" "$file" 2>/dev/null; then
         # Add section at the end
-        echo -e "\n[$section]" >>"$file"
+        echo -e "\n[$section]" | $sudo tee --append "$file" > /dev/null
     fi
     if ! ini_has_option "$file" "$section" "$option"; then
         # Add it
-        sed -i -e "/^\[$section\]/ a\\
+        $sudo sed -i -e "/^\[$section\]/ a\\
 $option = $value
 " "$file"
     else
         local sep=$(echo -ne "\x01")
         # Replace it
-        sed -i -e '/^\['${section}'\]/,/^\[.*\]/ s'${sep}'^\('${option}'[ \t]*=[ \t]*\).*$'${sep}'\1'"${value}"${sep} "$file"
+        $sudo sed -i -e '/^\['${section}'\]/,/^\[.*\]/ s'${sep}'^\('${option}'[ \t]*=[ \t]*\).*$'${sep}'\1'"${value}"${sep} "$file"
     fi
     $xtrace
 }
 
 # Set a multiple line option in an INI file
-# iniset_multiline config-file section option value1 value2 valu3 ...
+# iniset_multiline [-sudo] config-file section option value1 value2 valu3 ...
 function iniset_multiline {
     local xtrace=$(set +o | grep xtrace)
     set +o xtrace
+    local sudo=""
+    if [ $1 == "-sudo" ]; then
+        sudo="sudo "
+        shift
+    fi
     local file=$1
     local section=$2
     local option=$3
@@ -188,14 +218,14 @@
     done
     if ! grep -q "^\[$section\]" "$file"; then
         # Add section at the end
-        echo -e "\n[$section]" >>"$file"
+        echo -e "\n[$section]" | $sudo tee --append "$file" > /dev/null
     else
         # Remove old values
-        sed -i -e "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ d; }" "$file"
+        $sudo sed -i -e "/^\[$section\]/,/^\[.*\]/ { /^$option[ \t]*=/ d; }" "$file"
     fi
     # Add new ones
     for v in $values; do
-        sed -i -e "/^\[$section\]/ a\\
+        $sudo sed -i -e "/^\[$section\]/ a\\
 $option = $v
 " "$file"
     done
@@ -207,10 +237,15 @@
 function iniuncomment {
     local xtrace=$(set +o | grep xtrace)
     set +o xtrace
+    local sudo=""
+    if [ $1 == "-sudo" ]; then
+        sudo="sudo "
+        shift
+    fi
     local file=$1
     local section=$2
     local option=$3
-    sed -i -e "/^\[$section\]/,/^\[.*\]/ s|[^ \t]*#[ \t]*\($option[ \t]*=.*$\)|\1|" "$file"
+    $sudo sed -i -e "/^\[$section\]/,/^\[.*\]/ s|[^ \t]*#[ \t]*\($option[ \t]*=.*$\)|\1|" "$file"
     $xtrace
 }
 
diff --git a/tests/test_ini_config.sh b/tests/test_ini_config.sh
index 3aef6f3..61f2c41 100755
--- a/tests/test_ini_config.sh
+++ b/tests/test_ini_config.sh
@@ -71,15 +71,23 @@
 
 EOF
 
-# Test with missing arguments
+# set TEST_SUDO to test writing to root-owned files
+SUDO_ARG=""
+SUDO=""
+if [ -n "$TEST_SUDO" ]; then
+    SUDO="sudo "
+    SUDO_ARG="-sudo "
+    sudo chown -R root:root ${INI_TMP_ETC_DIR}
+fi
 
+# Test with missing arguments
 BEFORE=$(cat ${TEST_INI})
 
-iniset ${TEST_INI} aaa
+iniset ${SUDO_ARG} ${TEST_INI} aaa
 NO_ATTRIBUTE=$(cat ${TEST_INI})
 assert_equal "$BEFORE" "$NO_ATTRIBUTE" "test missing attribute argument"
 
-iniset ${TEST_INI}
+iniset ${SUDO_ARG} ${TEST_INI}
 NO_SECTION=$(cat ${TEST_INI})
 assert_equal "$BEFORE" "$NO_SECTION" "missing section argument"
 
@@ -87,7 +95,7 @@
 VAL=$(iniget ${TEST_INI} aaa handlers)
 assert_equal "$VAL" "aa, bb" "iniget spaces in option"
 
-iniset ${TEST_INI} aaa handlers "11, 22"
+iniset ${SUDO_ARG} ${TEST_INI} aaa handlers "11, 22"
 VAL=$(iniget ${TEST_INI} aaa handlers)
 assert_equal "$VAL" "11, 22" "iniset spaces in option"
 
@@ -95,7 +103,7 @@
 VAL=$(iniget ${TEST_INI} " ccc " spaces)
 assert_equal "$VAL" "yes" "iniget with section header space"
 
-iniset ${TEST_INI} "b b" opt_ion 42
+iniset ${SUDO_ARG} ${TEST_INI} "b b" opt_ion 42
 VAL=$(iniget ${TEST_INI} "b b" opt_ion)
 assert_equal "$VAL" "42" "iniset with section header space"
 
@@ -103,7 +111,7 @@
 VAL=$(iniget ${TEST_INI} bbb handlers)
 assert_equal "$VAL" "ee,ff" "iniget at EOF"
 
-iniset ${TEST_INI} bbb handlers "33,44"
+iniset ${SUDO_ARG} ${TEST_INI} bbb handlers "33,44"
 VAL=$(iniget ${TEST_INI} bbb handlers)
 assert_equal "$VAL" "33,44" "inset at EOF"
 
@@ -122,12 +130,12 @@
 fi
 
 # test changing empty option
-iniset ${TEST_INI} ddd empty "42"
+iniset ${SUDO_ARG} ${TEST_INI} ddd empty "42"
 VAL=$(iniget ${TEST_INI} ddd empty)
 assert_equal "$VAL" "42" "change empty option"
 
 # test pipe in option
-iniset ${TEST_INI} aaa handlers "a|b"
+iniset ${SUDO_ARG} ${TEST_INI} aaa handlers "a|b"
 VAL=$(iniget ${TEST_INI} aaa handlers)
 assert_equal "$VAL" "a|b" "pipe in option"
 
@@ -146,23 +154,23 @@
 fi
 
 # Test comments
-inicomment ${TEST_INI} aaa handlers
+inicomment ${SUDO_ARG} ${TEST_INI} aaa handlers
 VAL=$(iniget ${TEST_INI} aaa handlers)
 assert_empty VAL "test inicomment"
 
 # Test multiple line iniset/iniget
-iniset_multiline ${TEST_INI} eee multi bar1 bar2
+iniset_multiline ${SUDO_ARG} ${TEST_INI} eee multi bar1 bar2
 
 VAL=$(iniget_multiline ${TEST_INI} eee multi)
 assert_equal "$VAL" "bar1 bar2" "iniget_multiline"
 
 # Test iniadd with exiting values
-iniadd ${TEST_INI} eee multi bar3
+iniadd ${SUDO_ARG} ${TEST_INI} eee multi bar3
 VAL=$(iniget_multiline ${TEST_INI} eee multi)
 assert_equal "$VAL" "bar1 bar2 bar3" "iniadd with existing values"
 
 # Test iniadd with non-exiting values
-iniadd ${TEST_INI} eee non-multi foobar1 foobar2
+iniadd ${SUDO_ARG} ${TEST_INI} eee non-multi foobar1 foobar2
 VAL=$(iniget_multiline ${TEST_INI} eee non-multi)
 assert_equal "$VAL" "foobar1 foobar2" "iniadd non-existing values"
 
@@ -176,7 +184,7 @@
     del_no_section"
 
 for x in $del_cases; do
-    inidelete ${TEST_INI} $x a
+    inidelete ${SUDO_ARG} ${TEST_INI} $x a
     VAL=$(iniget_multiline ${TEST_INI} $x a)
     assert_empty VAL "inidelete $x"
     if [ "$x" = "del_separate_options" -o \
@@ -191,6 +199,6 @@
     fi
 done
 
-rm -rf ${INI_TMP_DIR}
+$SUDO rm -rf ${INI_TMP_DIR}
 
 report_results