|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
#
|
|
|
8d7a8a |
# Copyright (c) 2016, 2017, 2018, 2019, 2020, 2021, 2022, 2023 LucĂa Andrea Illanes Albornoz <lucia@luciaillanes.de>
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
# set +o errexit -o noglob -o nounset is assumed.
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
#
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
|
|
|
550c18 |
#
|
|
|
550c18 |
# rtl_basename() - obtain base name from filename
|
|
|
550c18 |
# @_rfname: inout reference to filename
|
|
|
550c18 |
#
|
|
|
550c18 |
# Returns: zero (0) on success, non-zero (>0) on failure
|
|
|
550c18 |
#
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
rtl_basename() {
|
|
|
e9fa07 |
rtl_basename2 "${1}" "${1}";
|
|
|
e9fa07 |
};
|
|
|
e9fa07 |
|
|
|
550c18 |
#
|
|
|
550c18 |
# rtl_basename2() - obtain base name from filename
|
|
|
550c18 |
# @_rfname: in reference to filename
|
|
|
550c18 |
# @_rfname_out: out reference to new filename
|
|
|
550c18 |
#
|
|
|
550c18 |
# Returns: zero (0) on success, non-zero (>0) on failure
|
|
|
550c18 |
#
|
|
|
e9fa07 |
rtl_basename2() {
|
|
|
e9fa07 |
local _rb2_rfname="${1#\$}" _rb2_rfname_out="${2#\$}" \
|
|
|
e9fa07 |
_rb2_fname="";
|
|
|
e9fa07 |
|
|
|
e9fa07 |
eval _rb2_fname="\${${_rb2_rfname}}";
|
|
|
e9fa07 |
eval ${_rb2_rfname_out}='${_rb2_fname##*/}';
|
|
|
e9fa07 |
return 0;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
};
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
|
|
|
550c18 |
#
|
|
|
550c18 |
# rtl_check_digest() - check digest of single file
|
|
|
550c18 |
# @_rdigest: out reference to digest of file
|
|
|
550c18 |
# @_fname: name of file to check
|
|
|
550c18 |
# @_digest_check: digest to check against
|
|
|
550c18 |
#
|
|
|
550c18 |
# Returns: zero (0) on success, non-zero (>0) on failure
|
|
|
550c18 |
#
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
rtl_check_digest() {
|
|
|
e9fa07 |
local _rcd_rdigest="${1#\$}" _rcd_fname="${2}" _rcd_digest_check="${3}" \
|
|
|
e9fa07 |
_rcd_digest="";
|
|
|
e9fa07 |
|
|
|
e9fa07 |
if ! [ -e "${_rcd_fname}" ]; then
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
return 1;
|
|
|
e9fa07 |
else set -- $(sha256sum "${_rcd_fname}");
|
|
|
e9fa07 |
_rcd_digest="${1}";
|
|
|
e9fa07 |
eval ${_rcd_rdigest}='${_rcd_digest}';
|
|
|
e9fa07 |
if [ "${_rcd_digest}" = "${_rcd_digest_check}" ]; then
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
return 0;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
else
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
return 1;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
fi;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
fi;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
};
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
|
|
|
550c18 |
#
|
|
|
550c18 |
# rtl_check_digest_file() - check digest of single file w/ digest file
|
|
|
550c18 |
# @_fname: name of file to check
|
|
|
550c18 |
# @_digest_check: digest to check against
|
|
|
550c18 |
# @_digest_fname: name of file containing digest
|
|
|
550c18 |
#
|
|
|
550c18 |
# Returns: zero (0) on success, non-zero (>0) on failure
|
|
|
550c18 |
#
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
rtl_check_digest_file() {
|
|
|
e9fa07 |
local _rcdf_fname="${1}" _rcdf_digest_check="${2}" _rcdf_digest_fname="${3}" \
|
|
|
e9fa07 |
_rcdf_digest="" _rcdf_digest_file="";
|
|
|
e9fa07 |
|
|
|
e9fa07 |
if ! [ -e "${_rcdf_digest_fname}" ]; then
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
return 1;
|
|
|
e9fa07 |
else _rcdf_digest_file="$(cat "${_rcdf_digest_fname}")";
|
|
|
e9fa07 |
if [ "${_rcdf_digest_file}" != "${_rcdf_digest_check}" ]\
|
|
|
e9fa07 |
|| ! rtl_check_digest \$_rcdf_digest "${_rcdf_fname}" \
|
|
|
e9fa07 |
"${_rcdf_digest_check}";
|
|
|
e9fa07 |
then
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
return 1;
|
|
|
e9fa07 |
else
|
|
|
e9fa07 |
return 0;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
fi;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
fi;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
};
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
|
|
|
550c18 |
#
|
|
|
550c18 |
# rtl_check_path_vars() - check pathname variables for validity
|
|
|
550c18 |
# @_rstatus: out reference to status string
|
|
|
550c18 |
# @_vnames: list of variable names
|
|
|
550c18 |
#
|
|
|
550c18 |
# Returns: zero (0) on success, non-zero (>0) on empty or unset pathname variable or pathname variable containing whitespace characters
|
|
|
550c18 |
#
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
rtl_check_path_vars() {
|
|
|
e9fa07 |
local _rcpv_rstatus="${1#\$}" _rcpv_vnames="${2}" \
|
|
|
e9fa07 |
_rcpv_rc=0 _rcpv_vname="" _rcpv_vname_val="";
|
|
|
e9fa07 |
|
|
|
e9fa07 |
for _rcpv_vname in ${_rcpv_vnames}; do
|
|
|
e9fa07 |
rtl_get_var_unsafe \$_rcpv_vname_val "${_rcpv_vname}";
|
|
|
e9fa07 |
if [ "${_rcpv_vname_val:+1}" != 1 ]; then
|
|
|
e9fa07 |
_rcpv_rc=1;
|
|
|
e9fa07 |
rtl_setrstatus "${_rcpv_rstatus}" 'Error: variable \`'"${_rcpv_vname}'"' is empty or unset.';
|
|
|
e9fa07 |
break;
|
|
|
e9fa07 |
elif [ "${_rcpv_vname_val#* *}" != "${_rcpv_vname_val}" ]; then
|
|
|
e9fa07 |
_rcpv_rc=2;
|
|
|
e9fa07 |
rtl_setrstatus "${_rcpv_rstatus}" 'Error: variable \`'"${_rcpv_vname}'"' contains one or more whitespace characters.';
|
|
|
e9fa07 |
break;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
fi;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
done;
|
|
|
e9fa07 |
return "${_rcpv_rc}";
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
};
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
|
|
|
550c18 |
#
|
|
|
550c18 |
# rtl_dirname() - obtain directory name from filename
|
|
|
550c18 |
# @_rfname: inout reference to {file,directory} name
|
|
|
550c18 |
#
|
|
|
550c18 |
# Returns: zero (0) on success, non-zero (>0) on failure
|
|
|
550c18 |
#
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
rtl_dirname() {
|
|
|
e9fa07 |
rtl_dirname2 "${1}" "${1}";
|
|
|
e9fa07 |
};
|
|
|
e9fa07 |
|
|
|
550c18 |
#
|
|
|
550c18 |
# rtl_dirname2() - obtain directory name from filename
|
|
|
550c18 |
# @_rfname: in reference to filename
|
|
|
550c18 |
# @_rfname_out: out reference to directory name
|
|
|
550c18 |
#
|
|
|
550c18 |
# Returns: zero (0) on success, non-zero (>0) on failure
|
|
|
550c18 |
#
|
|
|
e9fa07 |
rtl_dirname2() {
|
|
|
550c18 |
local _rfname="${1#\$}" _rdname_out="${2#\$}" \
|
|
|
e9fa07 |
_rd2_dname="";
|
|
|
e9fa07 |
|
|
|
550c18 |
eval _rd2_dname="\${${_rfname}}";
|
|
|
e9fa07 |
_rd2_dname="${_rd2_dname%/*}";
|
|
|
e9fa07 |
|
|
|
e9fa07 |
case "${_rd2_dname}" in
|
|
|
e9fa07 |
"") _rd2_dname="."; ;;
|
|
|
e9fa07 |
*) while rtl_matchr "${_rd2_dname}" "*/"; do
|
|
|
e9fa07 |
_rd2_dname="${_rd2_dname%/}";
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
done; ;;
|
|
|
e9fa07 |
esac;
|
|
|
e9fa07 |
|
|
|
e9fa07 |
eval ${_rdname_out}='${_rd2_dname}';
|
|
|
e9fa07 |
return 0;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
};
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
|
|
|
550c18 |
#
|
|
|
550c18 |
# rtl_exists_any() - check for existence of pathnames beneath directory
|
|
|
550c18 |
# @_subdir: single directory name
|
|
|
550c18 |
# @...: list of pathnames to check
|
|
|
550c18 |
#
|
|
|
550c18 |
# Returns: zero (0) on success, non-zero (>0) on failure
|
|
|
550c18 |
#
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
rtl_exists_any() {
|
|
|
e9fa07 |
local _rea_subdir="${1}"; shift;
|
|
|
e9fa07 |
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
while [ "${#}" -gt 0 ]; do
|
|
|
e9fa07 |
if [ -e "${_rea_subdir}/${1}" ]; then
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
return 0;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
else
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
shift;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
fi;
|
|
|
e9fa07 |
done;
|
|
|
e9fa07 |
return 1;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
};
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
|
|
|
550c18 |
#
|
|
|
550c18 |
# rtl_flock_acquire() - acquire file lock
|
|
|
550c18 |
# @_fd: single file descriptor
|
|
|
550c18 |
# @_conflict_exit_code: exit code on conflict
|
|
|
550c18 |
# @_wait: wait period in seconds
|
|
|
550c18 |
#
|
|
|
550c18 |
# Returns: zero (0) on success, non-zero (>0) on failure
|
|
|
550c18 |
#
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
rtl_flock_acquire() {
|
|
|
e9fa07 |
local _rfa_fd="${1}" _rfa_conflict_exit_code="${2:-253}" _rfa_wait="${3:-3600}";
|
|
|
e9fa07 |
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
while true; do
|
|
|
e9fa07 |
if flock \
|
|
|
e9fa07 |
-E "${_rfa_conflict_exit_code}" \
|
|
|
e9fa07 |
-w "${_rfa_wait}" \
|
|
|
e9fa07 |
"${_rfa_fd}";
|
|
|
e9fa07 |
then
|
|
|
e9fa07 |
return 0;
|
|
|
e9fa07 |
elif [ "${?}" -eq "${_rfa_conflict_exit_code}" ]; then
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
continue;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
else
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
return "${?}";
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
fi;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
done;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
};
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
|
|
|
550c18 |
#
|
|
|
550c18 |
# rtl_is_newer() - check if single file is newer than other single file
|
|
|
550c18 |
# @_new_fname: single name of newer file
|
|
|
550c18 |
# @_old_fname: single name of older file
|
|
|
550c18 |
#
|
|
|
550c18 |
# Returns: zero (0) if @_new_fname is newer, non-zero (>0) if @_old_fname is newer
|
|
|
550c18 |
#
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
rtl_is_newer() {
|
|
|
e9fa07 |
local _ris_new_fname="${1}" _ris_old_fname="${2}" \
|
|
|
e9fa07 |
_ris_new_ts="" _ris_old_ts="";
|
|
|
e9fa07 |
|
|
|
e9fa07 |
if ! [ -e "${_ris_old_fname}" ]; then
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
return 0;
|
|
|
e9fa07 |
else
|
|
|
e9fa07 |
_ris_new_ts="$(stat -c %Y "${_ris_new_fname}" 2>/dev/null)";
|
|
|
e9fa07 |
_ris_old_ts="$(stat -c %Y "${_ris_old_fname}" 2>/dev/null)";
|
|
|
e9fa07 |
|
|
|
e9fa07 |
if [ "${_ris_new_ts:-0}" -gt "${_ris_old_ts:-0}" ]; then
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
return 0;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
else
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
return 1;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
fi;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
fi;
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
};
|
|
Lucio Andrés Illanes Albornoz |
aeeaa0 |
|
|
|
550c18 |
#
|
|
|
938c5c |
# rtl_patch_files() - patch files
|
|
|
550c18 |
# @_patch_cwd: patch(1) -d directory
|
|
|
550c18 |
# @_strip_count: patch(1) strip count
|
|
|
550c18 |
# @_fn: name of function that produces patch filenames and takes the arguments @_rpatch_fname @_patch_idx @...
|
|
|
550c18 |
# @... optional arguments to pass to @_fn
|
|
|
550c18 |
#
|
|
|
550c18 |
# Returns: zero (0) on success, non-zero (>0) on failure
|
|
|
550c18 |
#
|
|
|
138059 |
rtl_patch_files() {
|
|
|
138059 |
local _rpf_patch_cwd="${1}" _rpf_strip_count="${2}" _rpf_fn="${3}" \
|
|
|
138059 |
_rpf_patch_fname="" _rpf_patch_idx=0;
|
|
|
138059 |
shift $((3 + 2));
|
|
|
138059 |
|
|
|
138059 |
_rpf_patch_idx=1;
|
|
|
138059 |
while "${_rpf_fn}" \
|
|
|
138059 |
\$_rpf_patch_fname "${_rpf_patch_idx}" \
|
|
|
138059 |
"${@}" \
|
|
|
138059 |
&& [ "${_rpf_patch_fname:+1}" = 1 ];
|
|
|
138059 |
do
|
|
|
138059 |
: $((_rpf_patch_idx += 1));
|
|
|
138059 |
if [ -r "${_rpf_patch_fname}" ]\
|
|
|
138059 |
&& ! patch \
|
|
|
138059 |
-b \
|
|
|
138059 |
-d "${_rpf_patch_cwd}" \
|
|
|
138059 |
"-p${_rpf_strip_count}" \
|
|
|
138059 |
< "${_rpf_patch_fname}";
|
|
|
138059 |
then
|
|
|
138059 |
return 1;
|
|
|
138059 |
fi;
|
|
|
138059 |
done;
|
|
|
138059 |
return 0;
|
|
|
138059 |
};
|
|
|
138059 |
|
|
|
938c5c |
#
|
|
|
938c5c |
# rtl_set_perms_treeV() - set mode bits of directories and files
|
|
|
938c5c |
# @_mode_dir: mode bits for directories
|
|
|
938c5c |
# @_mode_file_exec: mode bits for executable files
|
|
|
938c5c |
# @_mode_file_nonexec: mode bits for non-executable files
|
|
|
938c5c |
# @...: list of base directory pathnames as positional parameters; empty strings are ignored
|
|
|
938c5c |
#
|
|
|
938c5c |
# Returns: zero (0) on success, non-zero (>0) on failure
|
|
|
938c5c |
#
|
|
|
938c5c |
rtl_set_perms_treeV() {
|
|
|
938c5c |
local _rspt_mode_dir="${1}" _rspt_mode_file_exec="${2}" _rspt_mode_file_nonexec="${3}" \
|
|
|
938c5c |
_rspt_destdir="" _rspt_fname="" \
|
|
|
938c5c |
IFS IFS0="${IFS}";
|
|
|
938c5c |
shift 3;
|
|
|
938c5c |
|
|
|
938c5c |
for _rspt_destdir in "${@}"; do
|
|
|
938c5c |
if [ -e "${_rspt_destdir}" ]; then
|
|
|
938c5c |
rtl_set_IFS_nl;
|
|
|
938c5c |
|
|
|
938c5c |
for _rspt_fname in $(find "${_rspt_destdir}" -type d); do
|
|
|
938c5c |
if ! rtl_fileop chmod "${_rspt_mode_dir}" \
|
|
|
938c5c |
"${_rspt_fname}";
|
|
|
938c5c |
then
|
|
|
938c5c |
return 1;
|
|
|
938c5c |
fi;
|
|
|
938c5c |
done;
|
|
|
938c5c |
|
|
|
938c5c |
for _rspt_fname in $(find \
|
|
|
938c5c |
"${_rspt_destdir}" \
|
|
|
938c5c |
\( -not -perm /0111 \) \
|
|
|
938c5c |
-type f);
|
|
|
938c5c |
do
|
|
|
938c5c |
if ! rtl_fileop chmod "${_rspt_mode_file_nonexec}" \
|
|
|
938c5c |
"${_rspt_fname}";
|
|
|
938c5c |
then
|
|
|
938c5c |
return 1;
|
|
|
938c5c |
fi;
|
|
|
938c5c |
done;
|
|
|
938c5c |
|
|
|
938c5c |
for _rspt_fname in $(find \
|
|
|
938c5c |
"${_rspt_destdir}" \
|
|
|
938c5c |
-perm /0111 \
|
|
|
938c5c |
-type f);
|
|
|
938c5c |
do
|
|
|
938c5c |
if ! rtl_fileop chmod "${_rspt_mode_file_exec}" \
|
|
|
938c5c |
"${_rspt_fname}";
|
|
|
938c5c |
then
|
|
|
938c5c |
return 1;
|
|
|
938c5c |
fi;
|
|
|
938c5c |
done;
|
|
|
938c5c |
|
|
|
938c5c |
IFS="${IFS0}";
|
|
|
938c5c |
fi;
|
|
|
938c5c |
done;
|
|
|
938c5c |
return 0;
|
|
|
938c5c |
};
|
|
|
938c5c |
|
|
|
64844b |
# vim:filetype=sh textwidth=0
|