tod/util: add support for diff and write file access mode
diff --git a/README.md b/README.md
index 88acbad..ab8cdcd 100644
--- a/README.md
+++ b/README.md
@@ -176,6 +176,22 @@
 to say, it can depend on other modules holder.sh. Conceptually it can define a
 variable in terms of another holder.sh variable.
 
+It is possible to give each template defined in scheme.sh a file access mode by
+defining related *_UID, *_GID and *_FMODE variables in the holder.sh script. For
+instance, suppose a module called `testmode` defines a template named `my_conf_t`.
+It is possible to specify different file mode attributes this file needs to have
+by defining the following variables in `testmode/holder.sh`:
+```
+_TESTMOD_MY_CONF_T_FMODE_="0640"
+_TESTMOD_MY_CONF_T_GID_="33"
+_TESTMOD_MY_CONF_T_UID_="33"
+```
+Those variables are independent from each other, special care in their naming must
+be taking in order for io.sh to be able to pick them up when performing file I/O.
+The name structure for those special variables is as follows:
+```
+_<capital module name>_<capital template name>_<{UID|GID|FMODE}>_
+```
 ### scheme.sh
 -------------
 
diff --git a/util/io.sh b/util/io.sh
index 5641c00..663413b 100644
--- a/util/io.sh
+++ b/util/io.sh
@@ -90,7 +90,9 @@
 ${1}
 EOF
 	elif is_in_tree_instance_d $2; then
-		echo > $2; cat > $2 <<EOF
+		local -r _uid="$(stat -c '%u' $2)"
+		local -r _gid="$(stat -c '%g' $2)"
+		cat <<EOF | sudo -E -u "#$_uid" -g "#$_gid" tee $2
 ${1}
 EOF
 	else
@@ -103,7 +105,15 @@
 # @return : success if @2 is valid
 function appvar
 {
-	[ -f "$2" ] && catvar "$1" >> "$2" || lets -l -e "invalid: $2"
+	if [ -f "$2" ] && is_in_tree_instance_d $2; then
+		local -r _uid="$(stat -c '%u' $2)"
+		local -r _gid="$(stat -c '%g' $2)"
+		cat <<EOF | sudo -E -u "#$_uid" -g "#$_gid" tee -a $2
+${1}
+EOF
+	else
+		lets -l -e "invalid: $2"
+	fi
 }
 
 # @1      : (optional) absolute path to a valid file
@@ -236,8 +246,35 @@
 	done
 }
 
+# @1      : template name
+# @2      : absolute path to file
+function __file_mode
+{
+	local _mode="_${module^^}_${1^^}_FMODE_"
+	local _uid="_${module^^}_${1^^}_UID_"
+	local _gid="_${module^^}_${1^^}_GID_"
+
+	_uid="${!_uid}"; _gid="${!_gid}"; _mode="${!_mode}"
+
+	if [ -n "${_uid:-}" ] && [ -n "${_gid:-}" ]; then
+		lets -l -i "set uid:gid: ${_uid}:${_gid}"
+		sudo chown ${_uid}:${_gid} $2 || return $s_err
+	elif [ -n "${_uid:-}" ]; then
+		lets -l -i "set uid: ${_uid}"
+		sudo chown ${_uid} $2 || return $s_err
+	elif [ -n "${_gid:-}" ]; then
+		lets -l -i "set gid: ${_gid}"
+		sudo chgrp ${_gid} $2 || return $s_err
+	fi
+
+	if [ -n "${_mode:-}" ]; then
+		lets -l -i "set mode: ${_mode}"
+		sudo chmod ${_mode} $2 || return $s_err
+	fi
+}
+
 # @1      : (optional) option --dry
-# @2      : file text content
+# @2      : file template name
 # @3      : absolute path to a valid target file
 # @return : Success if @3 is valid
 # @desc   : Redirect a bash variable to stdout or file
@@ -273,7 +310,7 @@
 }
 
 # @1      : diff flags
-# @2      : file text content
+# @2      : file template name
 # @3      : absolute path to an existing file
 # @desc   : This function can diff an existing file against some new content
 function __diff_file
@@ -284,15 +321,42 @@
 		# NOTE: "$(echo "$1")" makes sure $1 isn't broken down into multiple
 		# strings according to the bash IFS expasion.
 		# FIXME: check __write_to_file
-		diff $flags $2 <(__write_to_file --dry "$(echo "$1")" $2)
+		diff $flags $2 \
+		     <(__write_to_file --dry "$(echo "$1")" $2) || return $s_err
+
+		# Check file access mode
+		local _mode="_${module^^}_${1^^}_FMODE_"
+		local _uid="_${module^^}_${1^^}_UID_"
+		local _gid="_${module^^}_${1^^}_GID_"
+
+		if [ -n "${!_uid}" ]; then
+			[ "$(stat -c '%u' $2)" -eq "${!_uid}" ] || {
+				echo >&2 "uid: $(stat -c '%u' $2) VS ${!_uid}"
+				return $s_err3
+			}
+		fi
+
+		if [ -n "${!_gid}" ]; then
+			[ "$(stat -c '%g' $2)" -eq "${!_gid}" ] || {
+				echo >&2 "gid: $(stat -c '%g' $2) VS ${!_gid}"
+				return $s_err3
+			}
+		fi
+
+		if [ -n "${!_mode}" ]; then
+			[ "$(stat -c '%04a' $2)" -eq "${!_mode}" ] || {
+				echo >&2 "mode: $(stat -c '%04a' $2) VS ${!_mode}"
+				return $s_err3
+			}
+		fi
 	else
-		lets -l -d "invalid file: $2"
+		lets -l -d "no such file: $2"
 		return $s_err2
 	fi
 }
 
 # @1      : diff flags
-# @2      : file text content
+# @2      : file template name
 # @3      : absolute path to an existing file
 # @desc   : This function can diff an existing file against some new content
 function is_file_diff
@@ -300,7 +364,7 @@
 	__diff_file "$1" "$2" "$3" &>/dev/null
 }
 
-# @1      : file text content
+# @1      : file template name
 # @2      : absolute path to a valid file
 function __splash_file
 {
@@ -311,17 +375,18 @@
 	flags+=" --color"
 #	flags+=" --ignore-blank-lines"
 
-	__diff_file "$flags" "$1" "$2" | lets -l -x "diff"
+	__diff_file "$flags" "$1" "$2" 2>&1 | lets -l -x "diff"
 	case "${PIPESTATUS[0]}" in
 		$s_ok   ) lets -l -i --phew "MATCH: $(basename "$2")" ;;
 		$s_err  ) lets -l -w "DIFFER: $(basename "$2")" ;;
 		$s_err2 ) lets -l -w "NOT-FOUND: $(basename "$2")" ;;
+		$s_err3 ) lets -l -w "FILE-MODE: $(basename "$2")" ;;
 	esac
 
 	return $s_ok
 }
 
-# @1      : file text content
+# @1      : file template name
 # @2      : absolute path to a valid file
 # @desc   : Update the content of an already generated file. This is useful when
 #         : the user doesn't want/need to recreate a new rootfs from scratch.
@@ -353,6 +418,8 @@
 			lets -l -e "failed to append $old_foot_tags"
 		fi
 	fi
+
+	[ -f "$2" ] && __file_mode $1 $2
 }
 
 function __create_file
@@ -363,7 +430,9 @@
 		lets -l -w "overriding: $(basename $2)"
 	fi
 
-	__write_to_file $dry "$1" "$2"
+	__write_to_file $dry "$1" "$2" || return $?
+
+	[ ! -f "$2" ] || __file_mode $1 $2
 }
 
 function __file_do_helper