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