commit b34d3795965beeb0a0f716b7b4b0a7a4c59e52cb
parent 1a6fd48def3ed490c5435bfdf4d5317a319479bd
Author: Jaromil <jaromil@dyne.org>
Date:   Mon, 14 Feb 2011 15:57:37 +0100
backup function using duplicity
working, but hairy since duplicity continues trying to connect
and password handling is not optimal
Diffstat:
2 files changed, 121 insertions(+), 1 deletion(-)
diff --git a/src/tomb b/src/tomb
@@ -840,6 +840,124 @@ exec_post_hooks() {
     fi
 }
 
+get_arg_tomb() {
+# set up variables to be used by caller:
+# tombfile - filename without path
+# tombdir  - directory where the tomb is
+# tombname - name of the tomb (filename without extension)
+# the full path is made with $tombdir/$tombfile
+    if [ -z $1 ]; then
+	error "internal: get_arg_tomb called without argument"
+	return 1
+    fi
+
+    # make sure there is a .tomb extension
+    arg=${1%%\.*}.tomb
+
+    if ! [ -r ${arg} ]; then
+	error "file not found: $arg"
+	return 1
+    fi
+
+    tombfile=`basename $arg`
+    tombdir=`dirname $arg`
+
+    file ${tombdir}/${tombfile} | grep -i 'luks encrypted file' 2>&1 >/dev/null
+    if [ $? != 0 ]; then
+	error "$arg is not a valid tomb file, operation aborted"
+	tomb-notify "Not a tomb." "$arg doesn't seems a real tomb."
+	return 1
+    fi
+
+    tombname=${tombfile%%\.*}
+    return 0
+}
+
+backup_tomb() { # FIXME - duplicity asks passwords too often
+    # using duplicity
+    which duplicity > /dev/null
+    if [ $? != 0 ]; then
+	error "duplicity not found, can't operate backup"
+	return 1
+    fi
+    if [ -z $CMD3 ]; then
+	error "backup command needs 2 arguments: tomb and destination url"
+	error "please refer to tomb(1) and duplicity(1) manuals for more information"
+	return 1
+    fi
+
+    # is it a tomb?
+    get_arg_tomb ${CMD2}
+    if [ $? != 0 ]; then
+	error "there is no tomb to backup, operation aborted."
+	return 1
+    fi
+
+    # is it a url?
+    echo "${CMD3}" | grep -i -e '^.*:\/\/.*' 2>&1 > /dev/null
+    if ! [ $? = 0 ]; then
+	error "second argument is not a valid duplicity url."
+	error "read the tomb(1) and duplicity(1) manual for more information"
+	return 1
+    fi
+    bckurl=${CMD3}
+
+    # is it ssh?
+    protocol="`expr substr $bckurl 1 3`"
+    act "backup over protocol $protocol"
+    if [ "$protocol" = "ssh" ]; then
+	act "ssh connection requires a password"
+	FTP_PASSWORD="`exec_as_user tomb askpass $bckurl`"
+	dupopts="--ssh-askpass"
+# TODO verify ssh access before duplicity does
+#      since it blocks the thing retrying 5 times and such crap
+#      i.e. try ssh true to sshurl="`echo $bckurl | sed -e 's/ssh:\/\///'`"
+#  --no-print-statistics
+    fi
+
+    # duplicity works only on directories
+    # so we create a directory in tmpfs and bind the tomb inside it
+    # during backup the encrypted tomb will be exposed
+    # TODO: check that the tomb is not mounted and, if mounted
+    #       remount it read-only so it doesn't gets modified during bck
+    bckname=${tombname}.bck
+    mkdir -p /dev/shm/${bckname}
+    if [ $? != 0 ]; then
+	error "cannot generate a temporary backup directory in /dev/shm, operation aborted."
+	return 1
+    fi
+    bcktmpdir=/dev/shm/${bckname}
+    # mmm, maybe we should mount our own tmpfs? we need root anyway for mount -o bind
+    # if we reach to eliminate this mount trick and upload only one file with duplicity
+    # then this function doesn't needs to be root to work.
+    touch ${bcktmpdir}/${tombfile}
+    mount -o bind ${tombdir}/${tombfile} ${bcktmpdir}/${tombfile}
+    bcklast=`exec_as_user duplicity \
+	${(s: :)dupopts} \
+	collection-status ${bckurl} \
+	| awk '/^Last full backup date:/ { print $5 }'`
+    # we detect if backup already exists or not so we can handle
+    # password prompt (choosing a password for full, inserting for incr)
+    if [ "$bcklast" = "none" ]; then
+	notice "Creating a backup of tomb $tombname on url $bckurl"
+	exec_as_user FTP_PASSWORD="$FTP_PASSWORD" duplicity ${(s: :)dupopts} \
+	    full ${bcktmpdir} ${bckurl}
+    else
+	notice "Updating a backup of tomb $tombname on url $bckurl"
+	exec_as_user FTP_PASSWORD="$FTP_PASSWORD" duplicity ${(s: :)dupopts} \
+	    incr ${bcktmpdir} ${bckurl}
+    fi
+    unset FTP_PASSWORD
+    if [ $? != 0 ]; then
+	error "duplicity reported error, operation aborted"
+	umount ${bcktmpdir}/${tombfile}
+	return 1
+    fi
+    notice "Operation successful."
+    umount ${bcktmpdir}/${tombfile}
+    return 0
+}
+
 umount_tomb() {
 
     if ! [ $1 ]; then
@@ -1029,6 +1147,8 @@ case "$CMD" in
     bury)     encode_key ${CMD2} ${CMD3} ;;
     exhume)   decode_key ${CMD2} ;;
 
+    backup)   check_priv ; backup_tomb ${CMD2} ${CMD3} ;;
+
     install)  check_priv ; install_tomb ;;
 
     askpass)  ask_password $CMD2 $CMD3 ;;
diff --git a/src/tomb-status.c b/src/tomb-status.c
@@ -89,7 +89,7 @@ int main(int argc, char **argv) {
   //  gtk_status_icon_set_name(status_tomb, "tomb");
   gtk_status_icon_set_title(status_tomb, "Tomb");
 
-  snprintf(tooltip,255,"Tomb in %s",mountpoint);
+  snprintf(tooltip,255,"%s",mountpoint);
   gtk_status_icon_set_tooltip_text (status_tomb, tooltip);
 
   // LEFT click menu