diff --git a/scripts/upload.sh b/scripts/upload.sh index fc55b855..37dc3b3d 100644 --- a/scripts/upload.sh +++ b/scripts/upload.sh @@ -33,7 +33,7 @@ MYNAME=`basename $0` HOST=ftp.jannet.de CFG_FILE=$HOME/.uploadrc -user=`whoami` +login=`whoami` method=rsync_ssh pw_ftp= pw_scp=$HOME/.ssh/identity @@ -54,27 +54,28 @@ cat << EOT Version '$Revision$' - '$Date$' (c) 2002 Jannet IT Services http://www.jannet.de - usage: $MYNAME file [password:[method:[user@]]]host:[target[:mode[:dirmode[:owner[.group]]]]] ... + usage: $MYNAME source [method://][[password:]login@]host[:target[:mode[:dirmode[:owner[.group]]]]] ... where "method" is one of "ftp", "scp", "rsync", "rsync_ssh". "password" may be a valid rsa private key file, too, if this makes sense with the chosen method. - "file" may be a directory and a file. If it ends with a slash, it is treated as an existing - directory and expands to its contents. + "source" may be a directory or a file. If it ends with a slash, it is treated as an existing + directory and expands to its contents. Thus, in the following, "source" denotes either a single + or multiple files or directories. - "target" may be a directory and a file. - + If it is an existing directory, it will be populated with "file", "file" will keep its name. - + If it is not an existing directory, $MYNAME will take the path from target (i.e., skip - everything following the last slash), and populate it with "file". - - If there is a nonempty file name following the last slash, this will be the new file name. - - If the last character of the target is a slash, the file name will be taken from "file". + "target" may be a directory or a file. + + If it is an existing directory, it will be populated with "source". "source" will keep its name. + + If it is not an existing directory, and does not have a trailing slash, + $MYNAME will skip everything following the last slash for a directory name, create + it, and populate it with "source". "source" will get renamed to the last portion of "target". + + If it is not an existing directory and has a trailing slash it will be created and populated with + "source". The default values for the optional parameters can be redefined in $CFG_FILE. - Currently they are: - user="$user" + login="$login" method="$method" pw_ftp="$pw_ftp" pw_scp="$pw_scp" @@ -92,11 +93,11 @@ EOT parse_target() { target=$1 - USER=`echo $target | sed -e '/@/ !d; s/@.*//; s/.*://'` - test -n "$USER" && echo user="\"$USER\";" - METHOD=`echo :$target | sed -e '/@/ !d; s/@.*//' | rev | cut -d: -f2 | rev` + USER=`echo $target | sed -e 's/^.*:\/\///; /@/ !d; s/@.*//; s/.*://'` + test -n "$USER" && echo login="\"$USER\";" + METHOD=`echo $target | sed -e 's/:\/\/.*//'` test -n "$METHOD" && echo method="\"$METHOD\";" - PASSWD=`echo :$target | sed -e '/@/ !d; s/@.*//' | rev | cut -d: -f3 | rev` + PASSWD=`echo $target | sed -e '/@/ !d; /@/ !d; s/^.*:\/\///; s/@.*//' | rev | cut -d: -f2 | rev` if [ -n "$PASSWD" ]; then echo passwd="\"$PASSWD\";" if [ -f "$PASSWD" ]; then @@ -107,32 +108,37 @@ parse_target() echo pw_rsync="\"$PASSWD\";" echo pw_rsync_ssh="\"$PASSWD\";" fi - HOST=`echo $target | sed -e 's/.*@//' | cut -d: -f1` + HOST=`echo $target | sed -e 's/^.*:\/\///; s/.*@//' | cut -d: -f1` if [ -n "$HOST" ]; then echo host="\"$HOST\";" else PARSE_TARGET=FALSE return fi - TARGET_FILE=`echo $target | sed -e 's/.*@//' | cut -d: -f2` + TARGET_FILE=`echo $target | sed -e 's/^.*:\/\///; s/.*@//; /:/ !d' | cut -d: -f2` if [ -n "$TARGET_FILE" ]; then echo target_file="\"$TARGET_FILE\";" else PARSE_TARGET=FALSE return fi - FILE_MODE=`echo $target | sed -e 's/.*@//' | cut -d: -f3` + FILE_MODE=`echo $target | sed -e 's/^.*:\/\///; s/.*@//; /:/ !d' | cut -d: -f3` test -n "$FILE_MODE" && echo file_mode="\"$FILE_MODE\";" - DIR_MODE=`echo $target | sed -e 's/.*@//' | cut -d: -f4` + DIR_MODE=`echo $target | sed -e 's/^.*:\/\///; s/.*@//; /:/ !d' | cut -d: -f4` test -n "$DIR_MODE" && echo dir_mode="\"$DIR_MODE\";" - FILE_OWNER=`echo $target | sed -e 's/.*@//' | cut -d: -f5 | cut -d. -f1` + FILE_OWNER=`echo $target | sed -e 's/^.*:\/\///; s/.*@//; /:/ !d' | cut -d: -f5 | cut -d. -f1` test -n "$FILE_OWNER" && echo file_owner="\"$FILE_OWNER\";" - FILE_GROUP=`echo $target | sed -e 's/.*@//' | cut -d: -f5 | cut -d. -f2` + FILE_GROUP=`echo $target | sed -e 's/^.*:\/\///; s/.*@//; /:/ !d' | cut -d: -f5 | cut -d. -f2` test -n "$FILE_GROUP" && echo file_group="\"$FILE_GROUP\";" echo "PARSE_TARGET=\"OK\";" } +ssh_exec_stdin() +{ + ssh -l $login $IDENTITY $host -C "SCRIPT=\`mktemp /tmp/$MYNAME""_XXXXXX\`; cat > \$SCRIPT; /bin/sh \$SCRIPT; rm \$SCRIPT" +} + ssh_mkdir() { set -e @@ -146,7 +152,7 @@ cat << EOT | mkdir \$path || break test -n "$2" && chown "$2" \$path || break test -n "$3" && chgrp "$3" \$path || break - test -n "$4" && chmod "$4" \$path || break + test -n "$4" && chmod "$4" \$path || break fi if [ ! -d \$path ]; then echo "failed to create directory \$path, owner=\$file_owner, group=\$file_group, mode=\$dir_mode" @@ -154,7 +160,32 @@ cat << EOT | fi done EOT - ssh -l $user $IDENTITY $host -C "SCRIPT=\`mktemp /tmp/$MYNAME""_XXXXXX\`; cat > \$SCRIPT; /bin/sh \$SCRIPT; rm \$SCRIPT" + ssh_exec_stdin +} + +ssh_chown() +{ + set -e + dir=`echo $1 | sed -e 's/\/[^\/]*$//; s/\/*$//'` +cat << EOT | + cd $1 + if [ -n "$2" ]; then chown -R $2 . ; fi + if [ -n "$3" ]; then chown -R $3 . ; fi +EOT + ssh_exec_stdin +} + +ssh_chmod() +{ + set -e + dir=`echo $1 | sed -e 's/\/[^\/]*$//; s/\/*$//'` +cat << EOT | + if [ -f "$1" ]; then + chmod $ + if [ -n "$2" ]; then find . -type f | xargs --no-run-if-empty chmod $2 ; fi + if [ -n "$3" ]; then find . -type d | xargs --no-run-if-empty chmod $3 ; fi +EOT + ssh_exec_stdin } # -- here we go @@ -166,7 +197,7 @@ shift # -- check run for t in $*; do - # parse_target $t + parse_target $t eval `parse_target $t` if [ "$PARSE_TARGET" != OK ]; then echo "Failed to parse target \"$t\"; exiting." @@ -176,9 +207,9 @@ for t in $*; do test "$METHOD" && method=$METHOD case $method in rsync_ssh) - if [ "$user" != root ]; then - if [ "$file_owner" -a "$file_owner" != "$user" ]; then - echo "File owner \"$file_owner\" is only legal, if you log in as \"$user\" or as \"root\"." + if [ "$login" != root ]; then + if [ "$file_owner" -a "$file_owner" != "$login" ]; then + echo "File owner \"$file_owner\" is only legal, if you log in as \"$login\" or as \"root\"." exit 1 fi fi @@ -199,7 +230,9 @@ for t in $*; do case $method in rsync_ssh) ssh_mkdir $target_file $file_owner $file_group $dir_mode || break - /usr/bin/rsync -az --links -e "/usr/bin/ssh -l $user $IDENTITY" $source $user@$host:$target_file + /usr/bin/rsync -az --links -e "/usr/bin/ssh -l $login $IDENTITY" $source $login@$host:$target_file + ssh_chown $target_file $file_owner $file_group + ssh_chmod $target_file $file_mode $dir_mode ;; *) echo "Internal error: \"$method\" is not implemented." >&2