#!/usr/bin/env bash # # Copyright 2023 David Vazgenovich Shakaryan qargs() { local arg str for arg; do [[ "${arg:-*}" =~ [^A-Za-z0-9%+./:=@_-] ]] && arg="${arg@Q}" str+=" ${arg}" done printf '%s\n' "${str:1}" } temp_dest="${1}" link_dest="${2}" [[ -n "${link_dest}" ]] || exit 0 [[ "${temp_dest}" =~ ^(rclone://([^:]+):)(.+) ]] || exit 1 prefix="${BASH_REMATCH[1]}" remote="${BASH_REMATCH[2]}" path="${BASH_REMATCH[3]}" [[ "${link_dest}" == "${prefix}"* ]] || exit 1 link="${link_dest#"${prefix}"}" conf="$(rclone config dump)" || exit 1 read -rd '' JQ <<'EOF' .[$k] | select(.type == "crypt" or .type == "sftp") // error("not crypt or sftp") | [.type, .remote] | @tsv EOF IFS=$'\t' read -r r_type r_remote < <( jq -rc --arg k "${remote}" "${JQ}" <<<"${conf}") || exit 1 if [[ "${r_type}" == 'crypt' ]]; then crypt="${remote}" [[ "${r_remote}" =~ ^([^:]+):(.*) ]] || exit 1 remote="${BASH_REMATCH[1]}" base="${BASH_REMATCH[2]:+${BASH_REMATCH[2]}/}" upath=0 ulink=0 while IFS=$'\t' read -r k v; do [[ "${k% }" == "${path}" ]] && path="${base}${v# }" && upath=1 [[ "${k% }" == "${link}" ]] && link="${base}${v# }" && ulink=1 done < <(rclone cryptdecode --reverse "${crypt}:" "${path}" "${link}") wait "$!" || exit 1 ((ulink && upath)) || exit 1 fi read -rd '' JQ <<'EOF' .[$k] | select(.type == "sftp") // error("not sftp") | select(.key_file_pass | not) // error("key uses passphrase") | [ (.key_file | select(.) // error("missing key") | "-i", (sub("^~"; env.HOME) | @sh)), (.known_hosts_file | select(.) | "-o", ("UserKnownHostsFile=\(sub("^~"; env.HOME))" | @sh)), (.port | select(.) | "-p", @sh), ("\(.user // error("missing user"))@\(.host // error("missing host"))" | @sh) ] | join(" ") EOF mapfile -td '' args < <( jq -rc --arg k "${remote}" "${JQ}" <<<"${conf}" | \ xargs -r printf '%s\0' [[ "${PIPESTATUS[0]}" -eq 0 && "${PIPESTATUS[1]}" -eq 0 ]]) wait "$!" || exit 1 ssh_cmd=(ssh -o BatchMode=yes "${args[@]}") cmd=("${ssh_cmd[@]}" "cp -al $(printf '%q' "${link}") $(printf '%q' "${path}")") echo "* $(qargs "${cmd[@]}")" "${cmd[@]}" || exit 1 "${ssh_cmd[@]}" "touch -c ${path@Q}" exit 0