diff --git a/appvm/copy_file.c b/appvm/copy_file.c index 5f7fc79..9e65c65 100644 --- a/appvm/copy_file.c +++ b/appvm/copy_file.c @@ -1,8 +1,10 @@ #include #include +#include "filecopy.h" + extern void notify_progress(int, int); -char * copy_file(int outfd, int infd, long long size) +int copy_file(int outfd, int infd, long long size) { char buf[4096]; long long written = 0; @@ -15,14 +17,24 @@ char * copy_file(int outfd, int infd, long long size) count = size - written; ret = read(infd, buf, count); if (!ret) - return("EOF while reading file"); + return COPY_FILE_READ_EOF; if (ret < 0) - return("error reading file"); + return COPY_FILE_READ_ERROR; if (!write_all(outfd, buf, ret)) - return("error writing file content"); + return COPY_FILE_WRITE_ERROR; notify_progress(ret, 0); written += ret; } - return NULL; + return COPY_FILE_OK; } +char * copy_file_status_to_str(int status) +{ + switch (status) { + case COPY_FILE_OK: return "OK"; + case COPY_FILE_READ_EOF: return "Unexpected end of data while reading"; + case COPY_FILE_READ_ERROR: return "Error reading"; + case COPY_FILE_WRITE_ERROR: return "Error writing"; + default: return "????????"; + } +} diff --git a/appvm/filecopy.h b/appvm/filecopy.h index b4f6638..1fcd2d0 100644 --- a/appvm/filecopy.h +++ b/appvm/filecopy.h @@ -6,13 +6,21 @@ #define LEGAL_EOF 31415926 struct file_header { -unsigned int namelen; -unsigned int mode; -unsigned long long filelen; -unsigned int atime; -unsigned int atime_nsec; -unsigned int mtime; -unsigned int mtime_nsec; + unsigned int namelen; + unsigned int mode; + unsigned long long filelen; + unsigned int atime; + unsigned int atime_nsec; + unsigned int mtime; + unsigned int mtime_nsec; }; -char * copy_file(int outfd, int infd, long long size); +enum { + COPY_FILE_OK, + COPY_FILE_READ_EOF, + COPY_FILE_READ_ERROR, + COPY_FILE_WRITE_ERROR +}; + +int copy_file(int outfd, int infd, long long size); +char *copy_file_status_to_str(int status); diff --git a/appvm/qfile-agent.c b/appvm/qfile-agent.c index f7e27a9..e33b61c 100644 --- a/appvm/qfile-agent.c +++ b/appvm/qfile-agent.c @@ -50,7 +50,7 @@ void write_headers(struct file_header *hdr, char *filename) { if (!write_all(1, hdr, sizeof(*hdr)) || !write_all(1, filename, hdr->namelen)) - gui_fatal("writing file headers to remove AppVM"); + exit(1); } int single_file_processor(char *filename, struct stat *st) @@ -67,15 +67,21 @@ int single_file_processor(char *filename, struct stat *st) hdr.mtime_nsec = st->st_mtim.tv_nsec; if (S_ISREG(mode)) { - char *ret; + int ret; fd = open(filename, O_RDONLY); if (!fd) gui_fatal("open %s", filename); hdr.filelen = st->st_size; write_headers(&hdr, filename); ret = copy_file(1, fd, hdr.filelen); - if (ret) - gui_fatal("Copying file %s: %s", filename, ret); + // if COPY_FILE_WRITE_ERROR, hopefully remote will produce a message + if (ret != COPY_FILE_OK) { + if (ret != COPY_FILE_WRITE_ERROR) + gui_fatal("Copying file %s: %s", filename, + copy_file_status_to_str(ret)); + else + exit(1); + } close(fd); } if (S_ISDIR(mode)) { @@ -89,7 +95,7 @@ int single_file_processor(char *filename, struct stat *st) hdr.filelen = st->st_size + 1; write_headers(&hdr, filename); if (!write_all(1, name, st->st_size + 1)) - gui_fatal("write to remote VM"); + exit(1); } return 0; } @@ -130,7 +136,7 @@ void send_vmname(char *vmname) memset(buf, 0, sizeof(buf)); strncat(buf, vmname, sizeof(buf) - 1); if (!write_all(1, buf, sizeof buf)) - gui_fatal("writing vmname to remote VM"); + exit(1); } char *get_item(char *data, char **current, int size) diff --git a/appvm/qvm-copy-to-vm b/appvm/qvm-copy-to-vm new file mode 100755 index 0000000..4817b43 --- /dev/null +++ b/appvm/qvm-copy-to-vm @@ -0,0 +1,69 @@ +#!/bin/sh +# +# The Qubes OS Project, http://www.qubes-os.org +# +# Copyright (C) 2010 Rafal Wojtczuk +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# + +if [ x"$1" = "x--with-progress" ] ; then + DO_PROGRESS=1 + shift +else + DO_PROGRESS=0 +fi + +if [ $# -lt 2 ] ; then + echo usage: $0 '[--with-progress] dest_vmname file [file]+' + exit 1 +fi + +VM="$1" +shift + +if [ $DO_PROGRESS = 1 ] ; then + SIZE=$(du --apparent-size -c "$@" | tail -1 | cut -f 1) +fi + +export PROGRESS_FILE=$(mktemp) +/usr/lib/qubes/qvm-trigger-copy-to-vm $VM "$@" +while ! [ -s $PROGRESS_FILE ] ; do + sleep 0.1 +done + +while true ; do + read agentpid sentsize agentstatus < $PROGRESS_FILE + if [ "x"$agentstatus = x ] ; then continue ; fi + if ! [ -e /proc/$agentpid ] ; then break ; fi + if [ "x"$agentstatus = xdone ] ; then break ; fi + CURRSIZE=$(($sentsize/1024)) + if [ $DO_PROGRESS = 1 ] ; then + echo -ne "\r sent $CURRSIZE/$SIZE KB " + fi + sleep 0.4 +done + +rm -f $PROGRESS_FILE +if [ $DO_PROGRESS = 1 ] ; then + echo +fi + +if ! [ "x"$agentstatus = xDONE ] ; then + exit 1 +else + exit 0 +fi diff --git a/appvm/qvm-copy-to-vm2.kde b/appvm/qvm-copy-to-vm2.kde index 879279b..7600bb5 100755 --- a/appvm/qvm-copy-to-vm2.kde +++ b/appvm/qvm-copy-to-vm2.kde @@ -23,17 +23,18 @@ VM=$(kdialog -inputbox "Enter the VM name to send files to:") if [ X$VM = X ] ; then exit 0 ; fi -SIZE=$(du -c "$@" | tail -1 | cut -f 1) +SIZE=$(du --apparent-size -c "$@" | tail -1 | cut -f 1) REF=$(kdialog --progressbar "Copy progress") qdbus $REF org.freedesktop.DBus.Properties.Set "" maximum $SIZE export PROGRESS_FILE=$(mktemp) -qvm-copy-to-vm2 $VM "$@" +/usr/lib/qubes/qvm-trigger-copy-to-vm $VM "$@" while ! [ -s $PROGRESS_FILE ] ; do sleep 0.1 done while true ; do read agentpid sentsize agentstatus < $PROGRESS_FILE + if [ "x"$agentstatus = x ] ; then continue ; fi if ! [ -e /proc/$agentpid ] ; then break ; fi if [ "x"$agentstatus = xdone ] ; then break ; fi CURRSIZE=$(($sentsize/1024)) @@ -43,6 +44,7 @@ done qdbus $REF close rm -f $PROGRESS_FILE -if ! [ "x"$agentstatus = xDONE ] ; then - kdialog --sorry 'Abnormal file copy termination; see /var/log/qubes/qrexec.xid.log in dom0 for more details' -fi +# we do not want a dozen error messages, do we +# if ! [ "x"$agentstatus = xDONE ] ; then +# kdialog --sorry 'Abnormal file copy termination; see /var/log/qubes/qrexec.xid.log in dom0 for more details' +# fi diff --git a/appvm/qvm-copy-to-vm2 b/appvm/qvm-trigger-copy-to-vm similarity index 100% rename from appvm/qvm-copy-to-vm2 rename to appvm/qvm-trigger-copy-to-vm diff --git a/appvm/unpack.c b/appvm/unpack.c index ad53ebf..eaa1744 100644 --- a/appvm/unpack.c +++ b/appvm/unpack.c @@ -38,14 +38,19 @@ void fix_times_and_perms(struct file_header *hdr, char *name) void process_one_file_reg(struct file_header *hdr, char *name) { - char *ret; + int ret; int fdout = open(name, O_WRONLY | O_CREAT | O_EXCL | O_NOFOLLOW, 0700); if (fdout < 0) do_exit(errno); ret = copy_file(fdout, 0, hdr->filelen); - if (ret) - do_exit(errno); + if (ret != COPY_FILE_OK) { + if (ret == COPY_FILE_READ_EOF + || ret == COPY_FILE_READ_ERROR) + do_exit(LEGAL_EOF); // hopefully remote will produce error message + else + do_exit(errno); + } close(fdout); fix_times_and_perms(hdr, name); } @@ -68,7 +73,7 @@ void process_one_file_link(struct file_header *hdr, char *name) if (hdr->filelen > MAX_PATH_LENGTH - 1) do_exit(ENAMETOOLONG); if (!read_all(0, content, hdr->filelen)) - do_exit(errno); + do_exit(LEGAL_EOF); // hopefully remote has produced error message content[hdr->filelen] = 0; if (symlink(content, name)) do_exit(errno); @@ -80,7 +85,7 @@ void process_one_file(struct file_header *hdr) if (hdr->namelen > MAX_PATH_LENGTH - 1) do_exit(ENAMETOOLONG); if (!read_all(0, namebuf, hdr->namelen)) - do_exit(errno); + do_exit(LEGAL_EOF); // hopefully remote has produced error message namebuf[hdr->namelen] = 0; if (S_ISREG(hdr->mode)) process_one_file_reg(hdr, namebuf); diff --git a/rpm_spec/core-appvm.spec b/rpm_spec/core-appvm.spec index f5b8fa0..5b4005b 100644 --- a/rpm_spec/core-appvm.spec +++ b/rpm_spec/core-appvm.spec @@ -54,6 +54,9 @@ exit 0 fi adduser --create-home user +su user -c 'mkdir -p /home/user/.gnome2/nautilus-scripts' +su user -c 'ln -s /usr/lib/qubes/qvm-copy-to-vm2.kde /home/user/.gnome2/nautilus-scripts/"Copy to other AppVM"' +su user -c 'ln -s /usr/bin/qvm-open-in-dvm2 /home/user/.gnome2/nautilus-scripts/"Open in DisposableVM"' mkdir -p $RPM_BUILD_ROOT/var/lib/qubes @@ -71,9 +74,10 @@ cp qubes_core_appvm $RPM_BUILD_ROOT/etc/init.d/ mkdir -p $RPM_BUILD_ROOT/var/lib/qubes mkdir -p $RPM_BUILD_ROOT/usr/bin cp qubes_timestamp qvm-open-in-dvm2 $RPM_BUILD_ROOT/usr/bin -cp qvm-copy-to-vm2 $RPM_BUILD_ROOT/usr/bin +cp qvm-copy-to-vm $RPM_BUILD_ROOT/usr/bin mkdir -p $RPM_BUILD_ROOT/usr/lib/qubes cp qvm-copy-to-vm2.kde $RPM_BUILD_ROOT/usr/lib/qubes +cp qvm-trigger-copy-to-vm $RPM_BUILD_ROOT/usr/lib/qubes cp ../qrexec/qrexec_agent $RPM_BUILD_ROOT/usr/lib/qubes cp dvm_file_editor qfile-agent qfile-agent-dvm qfile-unpacker $RPM_BUILD_ROOT/usr/lib/qubes cp ../common/meminfo-writer $RPM_BUILD_ROOT/usr/lib/qubes @@ -123,13 +127,14 @@ rm -rf $RPM_BUILD_ROOT %files %defattr(-,root,root,-) /etc/init.d/qubes_core_appvm -/usr/bin/qvm-copy-to-vm2 +/usr/bin/qvm-copy-to-vm /usr/lib/qubes/qvm-copy-to-vm2.kde /usr/bin/qvm-open-in-dvm2 /usr/lib/qubes/meminfo-writer /usr/lib/qubes/dvm_file_editor %{kde_service_dir}/qvm-copy.desktop %{kde_service_dir}/qvm-dvm.desktop +/usr/lib/qubes/qvm-trigger-copy-to-vm /usr/lib/qubes/qrexec_agent /usr/lib/qubes/qfile-agent /usr/lib/qubes/qfile-agent-dvm