summaryrefslogtreecommitdiff
path: root/wrappers/shadow-ar.sh
diff options
context:
space:
mode:
Diffstat (limited to 'wrappers/shadow-ar.sh')
-rwxr-xr-xwrappers/shadow-ar.sh246
1 files changed, 246 insertions, 0 deletions
diff --git a/wrappers/shadow-ar.sh b/wrappers/shadow-ar.sh
new file mode 100755
index 00000000..b363034c
--- /dev/null
+++ b/wrappers/shadow-ar.sh
@@ -0,0 +1,246 @@
+#!/bin/bash
+
+set -euf -o pipefail
+
+top="#TOP#"
+shadow_top="#SHADOW_TOP#"
+
+orig_ar="#ORIG_TOOL#"
+shadow_ar="#SHADOW_TOOL#"
+
+errors=()
+warnings=()
+skips=()
+
+orig_out=()
+shadow_out=()
+orig_input=()
+shadow_input=()
+orig_opts=()
+shadow_opts=()
+
+dump_log ()
+{
+ (
+ set +u
+ IFS=";"
+ cat <<EOF
+errors=(${errors[@]})
+warnings=(${warnings[@]})
+skips=(${skips[@]})
+orig_out=(${orig_out[@]})
+shadow_out=(${shadow_out[@]})
+orig_input=(${orig_input[@]})
+shadow_input=(${shadow_input[@]})
+orig_opts=($0 ${orig_opts[@]})
+shadow_opts=(${shadow_opts[@]})
+
+EOF
+ )
+}
+
+report_errors () {
+ res=$?
+ if [ $res != 0 ]; then
+ errors+=("wrapper failed with $res")
+ fi
+ if [ ${#errors[@]} != 0 ] \
+ || [ ${#warnings[@]} != 0 ] \
+ || [ ${#skips[@]} != 0 ]; then
+ (
+ /usr/bin/flock -e 9
+
+ if [ ${#errors[@]} != 0 ]; then
+ log=$shadow_top.errors
+ elif [ ${#warnings[@]} != 0 ]; then
+ log=$shadow_top.warnings
+ else
+ log=$shadow_top.skips
+ fi
+ dump_log >>$log
+ ) 9>>$shadow_top.lock
+ fi
+}
+
+trap report_errors EXIT
+
+if [ "$#" -gt 0 ] && [ ${#orig_opts[@]} = 0 ]; then
+ opt="$1"
+ shift
+
+ orig_opts+=("$opt")
+
+ case "$opt" in
+ "-M") skips+=("mri-script unsupported") ;;
+ "c"*) ;;
+ *) errors+=("orig expecting: crsPD, cqsL, etc.; got: $opt") ;;
+ esac
+else
+ errors+=("orig missing: action")
+fi
+
+while [ "$#" -gt 0 ]; do
+ opt="$1"
+ shift
+
+ orig_opts+=("$opt")
+
+ case "$opt" in
+ "-"*)
+ ;;
+ *)
+ if [ ${#orig_out[@]} = 0 ]; then
+ orig_out+=("$opt")
+ else
+ orig_input+=("$opt")
+ fi
+ ;;
+ esac
+done
+
+# orig_out is used only if command is not skipped
+if [ "${#orig_out[@]}" = 0 ] && [ ${#skips[@]} = 0 ]; then
+ errors+=("orig missing: orig_out")
+fi
+
+print_shadow_path ()
+{
+ local path="$1"
+ local prefix="${2-}"
+
+ case "$path" in
+ "/dev/null") echo "$path"; return ;;
+ "/"*) errors+=("Absolute path: $path") ;;
+ esac
+
+ # Check that we are under $top
+ case "$(pwd -P | sed -e "s#^$top##")" in
+ "/"*) errors+=("Running outside of $top") ;;
+ esac
+
+ echo "$(pwd -P)/$path" | sed -e "s#$top#$shadow_top${prefix}#"
+}
+
+generate_shadow_rsp ()
+{
+ local orig_rsp="$1"
+
+ local shadow_rsp orig_file shadow_file
+
+ shadow_rsp=$(print_shadow_path "$orig_rsp")
+ mkdir -p "$(dirname "$shadow_rsp")"
+ rm -f "$shadow_rsp"
+
+ if [ "$(stat --format=%s "$orig_rsp")" = 0 ]; then
+ touch "$shadow_rsp"
+ else
+ local quote delim=""
+ while read -d '' -r orig_file; do
+ # unquote orig
+ case "$orig_file" in
+ \'*\') quote="'"; orig_file=${orig_file:1:-1} ;;
+ *) quote="" ;;
+ esac
+ shadow_file=$(print_shadow_path "$orig_file")
+ if ! [ -e "$shadow_file" ]; then
+ shadow_file="$orig_file"
+ fi
+ # quote shadow
+ echo -ne "$delim$quote$shadow_file$quote" >> "$shadow_rsp"
+ delim=" "
+ done < <({ cat "$orig_rsp"; echo; } | xargs printf '%s\0')
+ fi
+
+ echo "$shadow_rsp"
+}
+
+make_shadow_opts ()
+{
+ local opt
+ local shadow_file
+
+ if [ "$#" -gt 0 ] && [ ${#shadow_opts[@]} = 0 ]; then
+ opt="$1"
+ shift
+
+ shadow_opts+=("$opt")
+
+ case "$opt" in
+ "c"*) ;;
+ *) errors+=("shadow expecting: crsPD, cqsL, etc.; got: $opt") ;;
+ esac
+ else
+ errors+=("shadow missing: action")
+ fi
+
+ while [ "$#" -gt 0 ]; do
+ opt="$1"
+ shift
+
+ case "$opt" in
+ "-"*) ;;
+ "@"*".rsp")
+ opt="${opt#@}"
+ if [ x"$(basename "$opt" .rsp)" = x"$(basename "${orig_out[*]}")" ]; then
+ opt=$(generate_shadow_rsp "$opt")
+ else
+ errors+=("RSP file $opt does not match orig_out ${orig_out[*]}")
+ fi
+ opt="@$opt"
+ ;;
+ "@"*)
+ errors+=("Unexpected option: $opt")
+ opt="${opt#@}"
+ # shellcheck disable=SC2046
+ make_shadow_opts $(cat "$opt")
+ continue
+ ;;
+ *)
+ shadow_file=$(print_shadow_path "$opt")
+ if [ ${#shadow_out[@]} = 0 ]; then
+ opt="$shadow_file"
+ shadow_out+=("$shadow_file")
+ elif [ -e "$shadow_file" ]; then
+ opt="$shadow_file"
+ shadow_input+=("$shadow_file")
+ fi
+ ;;
+ esac
+ shadow_opts+=("$opt")
+ done
+}
+
+if [ ${#errors[@]} = 0 ] && [ ${#skips[@]} = 0 ]; then
+ make_shadow_opts "${orig_opts[@]}"
+fi
+
+if [ ${#errors[@]} = 0 ] && [ ${#skips[@]} = 0 ]; then
+ shadow_log=$(print_shadow_path "${orig_out[*]}" "-logs")
+
+ mkdir -p "$(dirname "${shadow_out[*]}")"
+ mkdir -p "$(dirname "$shadow_log")"
+
+ dump_log > "$shadow_log"
+ echo "$shadow_ar" "${shadow_opts[@]}" >> "$shadow_log"
+ "$shadow_ar" "${shadow_opts[@]}" >> "$shadow_log" 2>&1 &
+ shadow_res=0 && wait $! || shadow_res=$?
+
+ if [ $shadow_res != 0 ]; then
+ errors+=("shadow_ar failed with $shadow_res")
+ elif ! [ -e "${shadow_out[*]}" ]; then
+ errors+=("shadow_ar failed to generate output")
+ else
+ shadow_link=$(IFS=""; print_shadow_path "${orig_out[*]}" "-default-A")
+ mkdir -p "$(dirname "$shadow_link")"
+ ln -s -f "${shadow_out[*]}" "$shadow_link"
+ fi
+fi
+
+"$orig_ar" "${orig_opts[@]}" < /dev/stdin &
+orig_res=0 && wait $! || orig_res=$?
+
+if [ $orig_res != 0 ]; then
+ errors+=("orig_ar failed with $orig_res")
+fi
+
+exit $orig_res