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