3 |
# distupload -- a script to upload software distributions to a server |
# distupload -- a script to upload software distributions to a server |
4 |
# |
# |
5 |
# This script is part of OSN Commons. Copyright (C) 2024 OSN, Inc. |
# This script is part of OSN Commons. Copyright (C) 2024 OSN, Inc. |
6 |
# |
# |
7 |
# OSN Commons is free software: you can redistribute it and/or modify it |
# OSN Commons is free software: you can redistribute it and/or modify it |
8 |
# under the terms of the GNU General Public License as published by |
# under the terms of the GNU General Public License as published by |
9 |
# the Free Software Foundation, either version 3 of the License, or |
# the Free Software Foundation, either version 3 of the License, or |
10 |
# (at your option) any later version. |
# (at your option) any later version. |
11 |
# |
# |
12 |
# OSN Commons is distributed in the hope that it will be useful, |
# OSN Commons is distributed in the hope that it will be useful, |
13 |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
# but WITHOUT ANY WARRANTY; without even the implied warranty of |
14 |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
28 |
version="1.0.0" |
version="1.0.0" |
29 |
|
|
30 |
check_requirements() { |
check_requirements() { |
31 |
if [ -z "$(command -v grep)" ]; then |
if [ -z "$(command -v grep)" ]; then |
32 |
echo "$me: GNU grep is required to use this script" >&2 |
echo "$me: GNU grep is required to use this script" >&2 |
33 |
exit 1 |
exit 1 |
34 |
fi |
fi |
96 |
|
|
97 |
if echo "$1" | grep -E "^$pattern$" >/dev/null 2>&1; then |
if echo "$1" | grep -E "^$pattern$" >/dev/null 2>&1; then |
98 |
return |
return |
99 |
fi |
fi |
100 |
|
|
101 |
echo "$me: invalid domain '$1'" >&2 |
echo "$me: invalid domain '$1'" >&2 |
102 |
exit 1 |
exit 1 |
111 |
} |
} |
112 |
|
|
113 |
check_files() { |
check_files() { |
114 |
local output=""; |
local output="" |
115 |
|
|
116 |
for file in "$@"; do |
for file in "$@"; do |
117 |
output=$(stat "$file" 2>&1) |
output=$(stat "$file" 2>&1) |
141 |
fi |
fi |
142 |
|
|
143 |
echo "$me: generating GPG signature for $file" |
echo "$me: generating GPG signature for $file" |
144 |
gpg --detach-sign --armor -o - -- "$file" > "$file.sig" |
gpg --detach-sign --armor -o - -- "$file" >"$file.sig" |
145 |
|
|
146 |
if [ $? -ne 0 ]; then |
if [ $? -ne 0 ]; then |
147 |
echo "$me: failed to generate signature for $file" >&2 |
echo "$me: failed to generate signature for $file" >&2 |
168 |
|
|
169 |
if [ $posargs -eq 0 ]; then |
if [ $posargs -eq 0 ]; then |
170 |
case "$1" in |
case "$1" in |
171 |
-h|-\?|--help) |
-h | -\? | --help) |
172 |
show_help |
show_help |
173 |
exit |
exit |
174 |
;; |
;; |
175 |
-v|--version) |
-v | --version) |
176 |
show_version |
show_version |
177 |
exit |
exit |
178 |
;; |
;; |
179 |
-m|--method) |
-m | --method) |
180 |
check_optarg $@ |
check_optarg $@ |
181 |
method="$2" |
method="$2" |
182 |
shift 2 |
shift 2 |
183 |
;; |
;; |
184 |
-q|--quiet) |
-q | --quiet) |
185 |
quiet=1 |
quiet=1 |
186 |
shift |
shift |
187 |
;; |
;; |
188 |
-r|--remote) |
-r | --remote) |
189 |
check_optarg $@ |
check_optarg $@ |
190 |
validate_domain "$2" |
validate_domain "$2" |
191 |
remote="$2" |
remote="$2" |
192 |
shift 2 |
shift 2 |
193 |
;; |
;; |
194 |
-l|--location) |
-l | --location) |
195 |
check_optarg $@ |
check_optarg $@ |
196 |
location="$2" |
location="$2" |
197 |
shift 2 |
shift 2 |
198 |
;; |
;; |
199 |
-p|--password) |
-p | --password) |
200 |
check_optarg $@ |
check_optarg $@ |
201 |
password="$2" |
password="$2" |
202 |
shift 2 |
shift 2 |
203 |
;; |
;; |
204 |
-u|--username) |
-u | --username) |
205 |
if [ -z "$2" ]; then |
if [ -z "$2" ]; then |
206 |
username="$USER" |
username="$USER" |
207 |
else |
else |
208 |
username="$2" |
username="$2" |
209 |
fi |
fi |
210 |
|
|
211 |
shift 2 |
shift 2 |
212 |
;; |
;; |
213 |
--) |
--) |
214 |
posargs=1 |
posargs=1 |
215 |
shift |
shift |
216 |
;; |
;; |
217 |
-*) |
-*) |
218 |
echo "$me: invalid option -- '$1'" >&2 |
echo "$me: invalid option -- '$1'" >&2 |
219 |
echo "Try '$me --help' for more information" >&2 |
echo "Try '$me --help' for more information" >&2 |
220 |
exit 1 |
exit 1 |
221 |
;; |
;; |
222 |
*) |
*) |
223 |
ended=1 |
ended=1 |
224 |
;; |
;; |
225 |
esac |
esac |
226 |
else |
else |
227 |
ended=1 |
ended=1 |
228 |
fi |
fi |
229 |
|
|
230 |
if [ $ended -eq 1 ]; then |
if [ $ended -eq 1 ]; then |
231 |
if [ ! -z "$files" ]; then |
if [ ! -z "$files" ]; then |
232 |
files="$files " |
files="$files " |
233 |
fi |
fi |
234 |
|
|
235 |
if echo "$file_name" | grep -q "[\ \'\"]"; then |
if echo "$file_name" | grep -q "[\ \'\"]"; then |
236 |
echo "$me: file names must not contain spaces or quotes" >&2 |
echo "$me: file names must not contain spaces or quotes" >&2 |
258 |
|
|
259 |
echo "$me: using $method to upload files to $target:$location" |
echo "$me: using $method to upload files to $target:$location" |
260 |
|
|
261 |
if [ ! -z "$username" ]; then |
if [ ! -z "$username" ]; then |
262 |
echo "$me: authenticating as $username" |
echo "$me: authenticating as $username" |
263 |
fi |
fi |
264 |
|
|
277 |
time_start=$(date +%s) |
time_start=$(date +%s) |
278 |
|
|
279 |
case $method in |
case $method in |
280 |
scp) |
scp) |
281 |
check_command scp |
check_command scp |
282 |
|
|
283 |
if [ ! -z "$password" ]; then |
if [ ! -z "$password" ]; then |
284 |
echo "$me: cannot make any use of the password provided via command line options when using scp" |
echo "$me: cannot make any use of the password provided via command line options when using scp" |
285 |
echo "$me: please enter the password when asked by scp" |
echo "$me: please enter the password when asked by scp" |
286 |
fi |
fi |
|
|
|
|
if [ $quiet -eq 1 ]; then |
|
|
scp -- $files "$target:$location" > /dev/null 2>&1 |
|
|
else |
|
|
scp -- $files "$target:$location" |
|
|
fi |
|
287 |
|
|
288 |
code=$? |
if [ $quiet -eq 1 ]; then |
289 |
|
scp -- $files "$target:$location" >/dev/null 2>&1 |
290 |
if [ $code -ne 0 ]; then |
else |
291 |
echo "$me: scp failed with exit code $code" >&2 |
scp -- $files "$target:$location" |
292 |
exit 1 |
fi |
293 |
fi |
|
294 |
|
code=$? |
295 |
|
|
296 |
|
if [ $code -ne 0 ]; then |
297 |
|
echo "$me: scp failed with exit code $code" >&2 |
298 |
|
exit 1 |
299 |
|
fi |
300 |
;; |
;; |
301 |
|
|
302 |
ftp|sftp) |
ftp | sftp) |
303 |
check_command $method |
check_command $method |
304 |
|
|
305 |
if [ -z "$username" ]; then |
if [ -z "$username" ]; then |
306 |
echo "$me: no username provided, using 'anonymous' as default" |
echo "$me: no username provided, using 'anonymous' as default" |
307 |
username=anonymous |
username=anonymous |
308 |
fi |
fi |
309 |
|
|
310 |
batch_file=$(mktemp) |
batch_file=$(mktemp) |
311 |
|
|
312 |
if [ $? -ne 0 ]; then |
if [ $? -ne 0 ]; then |
313 |
echo "$me: failed to create temporary file" >&2 |
echo "$me: failed to create temporary file" >&2 |
314 |
exit 1 |
exit 1 |
315 |
fi |
fi |
316 |
|
|
317 |
if [ "$method" = "ftp" ]; then |
if [ "$method" = "ftp" ]; then |
318 |
echo "user \"$username\" \"$password\"" > "$batch_file" |
echo "user \"$username\" \"$password\"" >"$batch_file" |
319 |
echo "passive on" >> "$batch_file" |
echo "passive on" >>"$batch_file" |
320 |
fi |
fi |
321 |
|
|
322 |
echo "cd $location" >> "$batch_file" |
echo "cd $location" >>"$batch_file" |
323 |
|
|
324 |
for file in $files; do |
for file in $files; do |
325 |
echo "put $file" >> "$batch_file" |
echo "put $file" >>"$batch_file" |
326 |
done |
done |
327 |
|
|
328 |
echo "bye" >> "$batch_file" |
echo "bye" >>"$batch_file" |
329 |
|
|
330 |
if [ "$method" = "sftp" ]; then |
if [ "$method" = "sftp" ]; then |
331 |
if [ $quiet -eq 1 ]; then |
if [ $quiet -eq 1 ]; then |
332 |
sftp -oBatchMode=no -b "$batch_file" "$target" > /dev/null 2>&1 |
sftp -oBatchMode=no -b "$batch_file" "$target" >/dev/null 2>&1 |
|
else |
|
|
sftp -oBatchMode=no -b "$batch_file" "$target" |
|
|
fi |
|
333 |
else |
else |
334 |
if [ $quiet -eq 1 ]; then |
sftp -oBatchMode=no -b "$batch_file" "$target" |
|
cat "$batch_file" | $method -inv "$remote" > /dev/null 2>&1 |
|
|
else |
|
|
cat "$batch_file" | $method -inv "$remote" |
|
|
fi |
|
335 |
fi |
fi |
336 |
|
else |
337 |
code=$? |
if [ $quiet -eq 1 ]; then |
338 |
|
cat "$batch_file" | $method -inv "$remote" >/dev/null 2>&1 |
339 |
if [ $code -ne 0 ]; then |
else |
340 |
echo "$me: $method failed with exit code $code" >&2 |
cat "$batch_file" | $method -inv "$remote" |
|
exit 1 |
|
341 |
fi |
fi |
342 |
;; |
fi |
343 |
|
|
344 |
*) |
code=$? |
345 |
echo "$me: unsupported method '$method'" >&2 |
|
346 |
|
if [ $code -ne 0 ]; then |
347 |
|
echo "$me: $method failed with exit code $code" >&2 |
348 |
exit 1 |
exit 1 |
349 |
|
fi |
350 |
|
;; |
351 |
|
|
352 |
|
*) |
353 |
|
echo "$me: unsupported method '$method'" >&2 |
354 |
|
exit 1 |
355 |
;; |
;; |
356 |
esac |
esac |
357 |
|
|
364 |
rm -f "$sigfile" |
rm -f "$sigfile" |
365 |
done |
done |
366 |
|
|
|
echo "$me: upload complete in ${time_diff}s" |
|
367 |
|
echo "$me: upload complete in ${time_diff}s" |