@@ -28,28 +28,78 @@ log() {
2828 fi
2929}
3030
31- # Generic curl handler function
32- curl_handler () {
33- local command=" $1 "
34- local hostname=" $2 "
35-
36- response=$( $command -w " %{http_code}" -o /dev/null)
37- curl_exit_code=$?
38-
39- if [ " $response " -ge 200 ] && [ " $response " -lt 300 ]; then
40- return 0
41- elif [ $curl_exit_code -ne 0 ]; then
42- log " ERROR" " $RED " " Connection error during request to $hostname (curl exit code: $curl_exit_code )."
43- return 1
44- elif [ " $response " -ge 400 ]; then
45- log " ERROR" " $RED " " Server error during request to $hostname (HTTP status code: $response )."
46- return 2
31+ # Fetch a URL to a destination file, validating status codes.
32+ # Usage: fetch "<url>" "<dest or empty>" "200 404"
33+ fetch () {
34+ local url=" $1 "
35+ local dest=" $2 "
36+ local accepted=" ${3:- 200} "
37+
38+ # If no dest given, just discard body
39+ local out
40+ if [ -n " $dest " ]; then
41+ # Write to ".tmp" files first, then move when success, to ensure we don't write partial files
42+ out=" ${dest} .tmp"
4743 else
48- log " ERROR" " $RED " " Unexpected response from $hostname (HTTP status code: $response )."
49- return 3
44+ out=" /dev/null"
45+ fi
46+
47+ response=$( curl --connect-timeout 5 --max-time 30 -s -w " %{http_code}" -o " $out " " $url " )
48+ local curl_exit_code=$?
49+
50+ if [ $curl_exit_code -ne 0 ]; then
51+ [ -n " $dest " ] && rm -f " $out "
52+ log " ERROR" " $RED " " Connection error during request to $url (curl exit code: $curl_exit_code )."
53+ return 1
54+ fi
55+
56+ for code in $accepted ; do
57+ if [ " $response " = " $code " ]; then
58+ # Accepted; only persist body for 2xx responses
59+ if [ -n " $dest " ]; then
60+ if [[ " $response " =~ ^2 ]]; then
61+ mv " $out " " $dest "
62+ else
63+ rm -f " $out "
64+ fi
65+ fi
66+ return 0
67+ fi
68+ done
69+
70+ # not accepted
71+ [ -n " $dest " ] && rm -f " $out "
72+ log " ERROR" " $RED " " Unexpected response from $url (HTTP $response )."
73+ return 2
74+ }
75+
76+
77+ # POST a file to a URL, validating status codes.
78+ # Usage: post_file "<url>" "<file>" "200"
79+ post_file () {
80+ local url=" $1 "
81+ local file=" $2 "
82+ local accepted=" ${3:- 200} "
83+
84+ response=$( curl --connect-timeout 5 --max-time 300 -s -w " %{http_code}" -o /dev/null -X POST -F " file=@$file " " $url " )
85+ local curl_exit_code=$?
86+
87+ if [ $curl_exit_code -ne 0 ]; then
88+ log " ERROR" " $RED " " Connection error during POST to $url (curl exit code: $curl_exit_code )."
89+ return 1
5090 fi
91+
92+ for code in $accepted ; do
93+ if [ " $response " -eq " $code " ]; then
94+ return 0
95+ fi
96+ done
97+
98+ log " ERROR" " $RED " " Unexpected response from $url (HTTP $response )."
99+ return 2
51100}
52101
102+
53103# Print help message
54104show_help () {
55105 cat << EOF
@@ -109,33 +159,27 @@ backup_one() {
109159 local address=" $2 "
110160 local port=" $3 "
111161
112- log " INFO" " $YELLOW " " Backing up device config/presets: $hostname ($address :$port )"
162+ log " INFO" " $YELLOW " " Backing up device config/presets/ir : $hostname ($address :$port )"
113163
114164 mkdir -p " $backup_dir "
115165
116- local cfg_url=" http://$address :$port /cfg.json"
117- local presets_url=" http://$address :$port /presets.json"
118- local cfg_dest=" ${backup_dir} /${hostname} .cfg.json"
119- local presets_dest=" ${backup_dir} /${hostname} .presets.json"
120-
121- # Write to ".tmp" files first, then move when success, to ensure we don't write partial files
122- local curl_command_cfg=" curl -s " $cfg_url " -o " $cfg_dest .tmp" "
123- local curl_command_presets=" curl -s " $presets_url " -o " $presets_dest .tmp" "
166+ local file_prefix=" ${backup_dir} /${hostname} "
124167
125- if ! curl_handler " $curl_command_cfg " " $hostname " ; then
168+ if ! fetch " http:// $address : $port /cfg.json " " ${file_prefix} .cfg.json " ; then
126169 log " ERROR" " $RED " " Failed to backup configuration for $hostname "
127- rm -f " $cfg_dest .tmp"
128170 return 1
129171 fi
130172
131- if ! curl_handler " $curl_command_presets " " $hostname " ; then
173+ if ! fetch " http:// $address : $port /presets.json " " ${file_prefix} .presets.json " ; then
132174 log " ERROR" " $RED " " Failed to backup presets for $hostname "
133- rm -f " $presets_dest .tmp"
134175 return 1
135- fi
176+ fi
177+
178+ # ir.json is optional
179+ if ! fetch " http://$address :$port /ir.json" " ${file_prefix} .ir.json" " 200 404" ; then
180+ log " ERROR" " $RED " " Failed to backup ir configs for $hostname "
181+ fi
136182
137- mv " $cfg_dest .tmp" " $cfg_dest "
138- mv " $presets_dest .tmp" " $presets_dest "
139183 log " INFO" " $GREEN " " Successfully backed up config and presets for $hostname "
140184 return 0
141185}
@@ -150,9 +194,8 @@ update_one() {
150194 log " INFO" " $YELLOW " " Starting firmware update for device: $hostname ($address :$port )"
151195
152196 local url=" http://$address :$port /update"
153- local curl_command=" curl -s -X POST -F " file=@$firmware " " $url " "
154197
155- if ! curl_handler " $curl_command " " $hostname " ; then
198+ if ! post_file " $url " " $firmware " " 200 " ; then
156199 log " ERROR" " $RED " " Failed to update firmware for $hostname "
157200 return 1
158201 fi
0 commit comments