out() { printf "$1 $2\n" "${@:3}"; } error() { out "==> ERROR:" "$@"; } msg() { out "==>" "$@"; } msg2() { out " ->" "$@";} die() { error "$@"; exit 1; } in_array() { local i for i in "${@:2}"; do [[ $1 = "$i" ]] && return done } api_fs_mount() { if ! mountpoint -q "$1"; then mount -B "$1" "$1" && ROOT_IS_BIND=1 fi && mount -t proc proc "$1/proc" -o nosuid,noexec,nodev && mount -t sysfs sys "$1/sys" -o nosuid,noexec,nodev && mount -t devtmpfs udev "$1/dev" -o mode=0755,nosuid && mount -t devpts devpts "$1/dev/pts" -o mode=0620,gid=5,nosuid,noexec && mount -t tmpfs shm "$1/dev/shm" -o mode=1777,nosuid,nodev && mount -t tmpfs run "$1/run" -o nosuid,nodev,mode=0755 && mount -t tmpfs tmp "$1/tmp" -o mode=1777,strictatime,nodev,nosuid,size=50M } api_fs_umount() { umount \ "$1/tmp" \ "$1/run" \ "$1/dev/shm" \ "$1/dev/pts" \ "$1/dev" \ "$1/sys" \ "$1/proc" (( ROOT_IS_BIND )) && umount "$1" } valid_number_of_base() { local base=$1 len=${#2} i= for (( i = 0; i < len; i++ )); do (( (${2:i:1} & ~(base - 1)) == 0 )) || return done } mangle() { local i= chr= out= unset {a..f} {A..F} for (( i = 0; i < ${#1}; i++ )); do chr=${1:i:1} case $chr in [[:space:]\\]) printf -v chr '%03o' "'$chr" out+=\\ ;;& # fallthrough *) out+=$chr ;; esac done printf '%s' "$out" } unmangle() { local i= chr= out= len=$(( ${#1} - 4 )) unset {a..f} {A..F} for (( i = 0; i < len; i++ )); do chr=${1:i:1} case $chr in \\) if valid_number_of_base 8 "${1:i+1:3}" || valid_number_of_base 16 "${1:i+1:3}"; then printf -v chr '%b' "${1:i:4}" (( i += 3 )) fi ;;& # fallthrough *) out+=$chr esac done printf '%s' "$out${1:i}" } fstype_is_pseudofs() { # list taken from util-linux source: libmount/src/utils.c local pseudofs_types=('anon_inodefs' 'autofs' 'bdev' 'binfmt_misc' 'cgroup' 'configfs' 'cpuset' 'debugfs' 'devfs' 'devpts' 'devtmpfs' 'dlmfs' 'fuse.gvfs-fuse-daemon' 'fusectl' 'hugetlbfs' 'mqueue' 'nfsd' 'none' 'pipefs' 'proc' 'pstore' 'ramfs' 'rootfs' 'rpc_pipefs' 'securityfs' 'sockfs' 'spufs' 'sysfs' 'tmpfs') in_array "$1" "${pseudofs_types[@]}" }