#!/bin/sh
unalias -a
export fname
die() {
printf '%s\n' "$*"
exit 1
}
flags() {
case "$1" in (*'!'*) f_bang=true;; (*) f_bang=false;; esac
case "$1" in (*p*) f_p=true;; (*) f_p=false;; esac
case "$1" in (*f*) f_f=true;; (*) f_f=false;; esac
case "$1" in (*r*) f_r=true;; (*) f_r=false;; esac
case "$1" in (*n*) f_n=true;; (*) f_n=false;; esac
case "$1" in (*N*) f_N=true;; (*) f_N=false;; esac
case "$1" in (*a*) f_a=true;; (*) f_a=false;; esac
case "$1" in (*i*) f_i=true;; (*) f_i=false;; esac
case "$1" in (*o*) f_o=true;; (*) f_o=false;; esac
}
print_flags() {
$f_bang && printf '!'
$f_p && printf p
$f_f && printf f
$f_r && printf r
$f_n && printf n
$f_N && printf N
$f_a && printf a
$f_i && printf i
$f_o && printf o
}
# TODO: search $PATH
if ! test -x /bin/readlink -o -x /usr/bin/readlink; then
# Hackity hack. If you know of better way, let me know.
if test -x /bin/rsync -o -x /usr/bin/rsync; then
readlink() {
rsync -l8 --list-only "$1" | sed 's|^.* ->||'
}
else
readlink() {
ls -ld "$1" | sed 's|^.* ->||'
}
fi
fi
: ${check_only:=false}
req() {
if ! "check_$@"; then
if $check_only; then
die "check failed on '$fname': $* ($(print_flags))"
else
"do_$@" || die "action failed on '$fname': $* ($(print_flags))"
check_only=true
req "$@"
check_only=false
fi
fi
}
check_p() {
test -d "$(dirname "$fname")"
}
do_p() {
mkdir -p "$(dirname "$fname")" || exit $?
}
check_type_or_missing() {
test '!' -e "$fname" -o "-$1" "$fname"
}
do_type_or_missing() {
if $f_r; then
if $f_f; then
rm -rf "$fname" || exit $?
else
rm -r "$fname" || exit $?
fi
elif test -d "$fname"; then
rmdir "$fname"
else
if $f_f; then
rm -f "$fname" || exit $?
else
rm "$fname" || exit $?
fi
fi
}
do_l() {
if test -L "$fname"; then
rm "$fname"
elif test -e "$fname"; then
die "already present but not a symbolic link: $fname"
fi
ln -s "$1" "$fname" || exit $?
}
check_l() {
if $f_p; then
req p
fi
if $f_bang; then
req type_or_missing L
fi
test -L "$fname" && test x"$(readlink "$fname")" = x"$1"
}
l() {
req l "$@"
}
check_r() {
! test -e "$fname" -o -L "$fname"
}
do_r() {
do_type_or_missing
}
r() {
req r "$@"
}
check_m() {
test -e "$fname" -o -L "$fname" && \
test 0 -lt $(find "$fname" -prune -perm "$1" | wc -l)
}
do_m() {
chmod "$1" "$fname"
}
m() {
req m "$@"
}
check_o() {
test -e "$fname" -o -L "$fname" || return 1
case "$1" in
(*:*) test 0 -lt $( \
find "$fname" -prune -user "${1%:*}" -group "${1#*:}" | wc -l \
)
return $?;;
(*) test 0 -lt $(find "$fname" -prune -user "$1" | wc -l)
return $?;;
esac
}
do_o() {
chown "$1" "$fname"
}
o() {
req o "$@"
}
check_f() {
if test -f "$fname"; then
return 0
fi
if $f_p; then
req p
fi
if $f_bang; then
req type_or_missing f
elif test -e "$fname" -o -L "$fname"; then
die "already present but not a file: $fname"
fi
return 1
}
do_f() {
touch "$fname"
}
f() {
req f "$@"
}
check_d() {
if test -d "$fname"; then
return 0
fi
if $f_bang; then
req type_or_missing d
elif test -e "$fname" -o -L "$fname"; then
die "already present but not a directory: $fname"
fi
return 1
}
do_d() {
if $f_p; then
mkdir -p "$fname"
else
mkdir "$fname"
fi
}
d() {
req d "$@"
}
check_c() {
req f
"$@" | cmp -s - "$fname"
}
do_c() {
"$@" > "$fname"
}
c() {
req c "$@"
}