Blame subr.rtl/rtl_filepath.subr

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