diff --git a/src/progress.sh b/src/progress.sh index a2cdceb..5ee3283 100644 --- a/src/progress.sh +++ b/src/progress.sh @@ -2,6 +2,7 @@ set -Eeuo pipefail info="/run/shm/msg.html" +info_tmp="${info}.${BASHPID}.tmp" escape() { @@ -17,6 +18,23 @@ escape() { return 0 } +writeInfo() { + + local content="$1" + + if ! printf '%s\n' "$content" > "$info_tmp"; then + rm -f -- "$info_tmp" + return 1 + fi + + if ! mv -f -- "$info_tmp" "$info"; then + rm -f -- "$info_tmp" + return 1 + fi + + return 0 +} + getBytes() { local path="$1" @@ -48,6 +66,24 @@ getBytes() { return 0 } +getStatus() { + + local file="$1" + local bytes total extra="" + + [ -r "$file" ] || return 1 + read -r bytes total extra < "$file" || return 1 + + if [[ ! "$bytes" =~ ^[0-9]+$ || + ! "$total" =~ ^[0-9]+$ || + -n "$extra" ]]; then + return 1 + fi + + printf '%s %s\n' "$bytes" "$total" + return 0 +} + formatSize() { local bytes="$1" @@ -117,7 +153,9 @@ printSizeProgress() { return 0 } -finishLogProgress() { +finishProgress() { + + rm -f -- "$info_tmp" if [[ "$output" == "log" && "$printed" == "Y" ]]; then printf '\n' @@ -132,6 +170,7 @@ body=$(escape "$3") output="${4:-}" step_bytes="${5:-536870912}" mode="${6:-apparent}" +status_file="${7:-}" if [[ -n "$total" && ! "$total" =~ ^(0|[1-9][0-9]*)$ ]]; then printf 'Invalid total size: %s\n' "$total" >&2 @@ -168,7 +207,7 @@ if [ -z "$total" ] || [[ "$total" == "0" ]]; then log_mode="size" fi -trap finishLogProgress EXIT +trap finishProgress EXIT trap 'exit 0' HUP INT QUIT TERM if [[ "$body" == *"..." ]]; then @@ -178,12 +217,32 @@ fi while true; do bytes=$(getBytes "$path" "$mode") + effective_total="$total" + + if [ -n "$status_file" ] && status=$(getStatus "$status_file"); then + read -r status_bytes status_total <<< "$status" + bytes="$status_bytes" + + if (( status_total > 0 )); then + effective_total="$status_total" + fi + fi + + # A real total may become available shortly after aria2 starts. + if [[ "$log_mode" == "size" && + "$printed" == "N" && + -n "$effective_total" && + "$effective_total" != "0" ]]; then + log_mode="percent" + fi if (( bytes > 4096 )); then write_html="Y" - if [ -z "$total" ] || [[ "$total" == "0" ]] || (( bytes > total )); then + if [ -z "$effective_total" ] || + [[ "$effective_total" == "0" ]] || + (( bytes > effective_total )); then size=$(formatSize "$bytes") if [[ "$output" == "log" ]]; then @@ -197,7 +256,7 @@ while true; do fi else # Truncate to one decimal so progress is never reported early. - progress=$((bytes * 1000 / total)) + progress=$((bytes * 1000 / effective_total)) (( progress > 1000 )) && progress=1000 percent=$((progress / 10)) @@ -219,7 +278,7 @@ while true; do fi if [[ "$write_html" == "Y" ]]; then - printf '%s\n' "${body//(\[P\])/($size)}" > "$info" + writeInfo "${body//(\[P\])/($size)}" fi fi diff --git a/src/socket.sh b/src/socket.sh index 8bda7ad..5b620e0 100644 --- a/src/socket.sh +++ b/src/socket.sh @@ -3,6 +3,8 @@ set -Eeuo pipefail lastmsg="" path="/run/shm/msg.html" +dir=$(dirname -- "$path") +name=$(basename -- "$path") refresh() { @@ -17,15 +19,26 @@ refresh() { lastmsg="$msg" echo "s: $msg" + return 0 } refresh -inotifywait -m "$path" | - while read -r fp event fn; do +inotifywait \ + -m -q \ + -e close_write,moved_to,delete \ + --format '%e %f' \ + "$dir" | + while read -r event file; do + + [[ "$file" == "$name" ]] || continue + case "${event,,}" in - "modify"* ) refresh ;; - "delete_self" ) echo "c: vnc" ;; - esac + "delete"* ) + echo "c: vnc" ;; + "close_write"* | "moved_to"* ) + refresh ;; + esac + done diff --git a/src/utils.sh b/src/utils.sh index b764146..6196f55 100644 --- a/src/utils.sh +++ b/src/utils.sh @@ -300,6 +300,25 @@ writeFile() { return 0 } +writeAtomic() { + + local path="$1" + local content="$2" + local tmp="${path}.${BASHPID}.tmp" + + if ! printf '%s\n' "$content" > "$tmp"; then + rm -f -- "$tmp" + return 1 + fi + + if ! mv -f -- "$tmp" "$path"; then + rm -f -- "$tmp" + return 1 + fi + + return 0 +} + readFile() { local path="$1" @@ -411,8 +430,8 @@ html() { HTML="${HTML/\[4\]/$footer}" HTML="${HTML/\[5\]/$FOOTER2}" - echo "$HTML" > "$PAGE" || return 1 - echo "$body" > "$INFO" || return 1 + writeAtomic "$PAGE" "$HTML" || return 1 + writeAtomic "$INFO" "$body" || return 1 return 0 }