Added qfile-agent

This commit is contained in:
Rafal Wojtczuk 2011-03-15 16:07:00 +01:00
parent 66bf0abb53
commit b8d983cfa9
5 changed files with 253 additions and 3 deletions

View File

@ -1,10 +1,12 @@
CC=gcc CC=gcc
CFLAGS=-Wall -I../common CFLAGS=-Wall -I../common
all: qubes_penctl qubes_add_pendrive_script qvm-open-in-dvm dvm_file_editor qfile-agent-dvm all: qubes_penctl qubes_add_pendrive_script qvm-open-in-dvm dvm_file_editor qfile-agent-dvm qfile-agent
dvm_file_editor: dvm_file_editor.o ../common/ioall.o dvm_file_editor: dvm_file_editor.o ../common/ioall.o
$(CC) -o dvm_file_editor dvm_file_editor.o ../common/ioall.o $(CC) -o dvm_file_editor dvm_file_editor.o ../common/ioall.o
qfile-agent-dvm: qfile-agent-dvm.o ../common/ioall.o ../common/gui-fatal.o qfile-agent-dvm: qfile-agent-dvm.o ../common/ioall.o ../common/gui-fatal.o
$(CC) -o qfile-agent-dvm qfile-agent-dvm.o ../common/ioall.o ../common/gui-fatal.o $(CC) -o qfile-agent-dvm qfile-agent-dvm.o ../common/ioall.o ../common/gui-fatal.o
qfile-agent: qfile-agent.o ../common/ioall.o ../common/gui-fatal.o copy_file.o
$(CC) -o qfile-agent qfile-agent.o ../common/ioall.o ../common/gui-fatal.o copy_file.o
qubes_penctl: qubes_penctl.o qubes_penctl: qubes_penctl.o
$(CC) -o qubes_penctl qubes_penctl.o -lxenstore $(CC) -o qubes_penctl qubes_penctl.o -lxenstore
qubes_add_pendrive_script: qubes_add_pendrive_script.o qubes_add_pendrive_script: qubes_add_pendrive_script.o

28
appvm/copy_file.c Normal file
View File

@ -0,0 +1,28 @@
#include <unistd.h>
#include <ioall.h>
extern void notify_progress(int, int);
char * copy_file(int outfd, int infd, long long size)
{
char buf[4096];
long long written = 0;
int ret;
int count;
while (written < size) {
if (size - written > sizeof(buf))
count = sizeof buf;
else
count = size - written;
ret = read(infd, buf, count);
if (!ret)
return("EOF while reading file");
if (ret < 0)
return("error reading file");
if (!write_all(outfd, buf, ret))
return("error writing file content");
notify_progress(ret, 0);
written += ret;
}
return NULL;
}

18
appvm/filecopy.h Normal file
View File

@ -0,0 +1,18 @@
#define FILECOPY_SPOOL "/home/user/.filecopyspool"
#define FILECOPY_VMNAME_SIZE 32
#define PROGRESS_NOTIFY_DELTA (15*1000*1000)
#define MAX_PATH_LENGTH 16384
#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;
};
char * copy_file(int outfd, int infd, long long size);

201
appvm/qfile-agent.c Normal file
View File

@ -0,0 +1,201 @@
#define _GNU_SOURCE
#include <dirent.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <signal.h>
#include <fcntl.h>
#include <malloc.h>
#include <stdlib.h>
#include <ioall.h>
#include <unistd.h>
#include <gui-fatal.h>
#include "filecopy.h"
char *client_flags;
void do_notify_progress(long long total)
{
FILE *progress;
if (!client_flags[0])
return;
progress = fopen(client_flags, "w");
if (!progress)
return;
fprintf(progress, "%d %lld", getpid(), total);
fclose(progress);
}
void notify_progress(int size, int force)
{
static long long total = 0;
static long long prev_total = 0;
total += size;
if (total > prev_total + PROGRESS_NOTIFY_DELTA || force) {
do_notify_progress(total);
prev_total = total;
}
}
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");
}
int single_file_processor(char *filename, struct stat *st)
{
struct file_header hdr;
int fd;
mode_t mode = st->st_mode;
hdr.namelen = strlen(filename) + 1;
hdr.mode = mode;
hdr.atime = st->st_atim.tv_sec;
hdr.atime_nsec = st->st_atim.tv_nsec;
hdr.mtime = st->st_mtim.tv_sec;
hdr.mtime_nsec = st->st_mtim.tv_nsec;
if (S_ISREG(mode)) {
char * 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);
close(fd);
}
if (S_ISDIR(mode)) {
hdr.filelen = 0;
write_headers(&hdr, filename);
}
if (S_ISLNK(mode)) {
char name[st->st_size + 1];
if (readlink(filename, name, sizeof(name)) != st->st_size)
gui_fatal("readlink %s", filename);
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");
}
return 0;
}
int do_fs_walk(char *file)
{
char *newfile;
struct stat st;
struct dirent *ent;
DIR *dir;
if (lstat(file, &st))
gui_fatal("stat %s", file);
single_file_processor(file, &st);
if (!S_ISDIR(st.st_mode))
return 0;
dir = opendir(file);
if (!dir)
gui_fatal("opendir %s", file);
while ((ent = readdir(dir))) {
char *fname = ent->d_name;
if (!strcmp(fname, ".") || !strcmp(fname, ".."))
continue;
asprintf(&newfile, "%s/%s", file, fname);
do_fs_walk(newfile);
free(newfile);
}
closedir(dir);
// directory metadata is resent; this makes the code simple,
// and the atime/mtime is set correctly at the second time
single_file_processor(file, &st);
return 0;
}
void send_vmname(char *vmname)
{
char buf[FILECOPY_VMNAME_SIZE];
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");
}
char *get_item(char *data, char **current, int size)
{
char *ret;
if ((unsigned long) *current >= (unsigned long) data + size)
return NULL;
ret = *current;
*current += strlen(ret) + 1;
return ret;
}
void parse_entry(char *data, int datasize)
{
char *current = data;
char *vmname, *entry, *sep;
vmname = get_item(data, &current, datasize);
client_flags = get_item(data, &current, datasize);
notify_progress(0, 1);
send_vmname(vmname);
while ((entry = get_item(data, &current, datasize))) {
sep = rindex(entry, '/');
if (!sep)
gui_fatal("Internal error: nonabsolute filenames not allowed");
*sep = 0;
if (entry[0] == 0)
chdir("/");
else if (chdir(entry))
gui_fatal("chdir to %s", entry);
do_fs_walk(sep + 1);
}
notify_progress(0, 1);
}
void process_spoolentry(char *entry_name)
{
char *abs_spool_entry_name;
int entry_fd;
struct stat st;
char *entry;
int entry_size;
asprintf(&abs_spool_entry_name, "%s/%s", FILECOPY_SPOOL,
entry_name);
entry_fd = open(abs_spool_entry_name, O_RDONLY);
unlink(abs_spool_entry_name);
if (entry_fd < 0 || fstat(entry_fd, &st))
gui_fatal("bad file copy spool entry");
entry_size = st.st_size;
entry = calloc(1, entry_size + 1);
if (!entry)
gui_fatal("malloc");
if (!read_all(entry_fd, entry, entry_size))
gui_fatal("read filecopy entry");
close(entry_fd);
parse_entry(entry, entry_size);
}
void scan_spool(char *name)
{
struct dirent *ent;
DIR *dir = opendir(name);
if (!dir)
gui_fatal("opendir %s", name);
while ((ent = readdir(dir))) {
char *fname = ent->d_name;
if (fname[0] != '.')
process_spoolentry(fname);
break;
}
closedir(dir);
}
int main()
{
signal(SIGPIPE, SIG_IGN);
scan_spool(FILECOPY_SPOOL);
return 0;
}

View File

@ -76,7 +76,7 @@ cp qubes_timestamp qvm-copy-to-vm qvm-open-in-dvm qvm-open-in-dvm2 $RPM_BUILD_RO
mkdir -p $RPM_BUILD_ROOT/usr/lib/qubes mkdir -p $RPM_BUILD_ROOT/usr/lib/qubes
cp qubes_add_pendrive_script qubes_penctl qvm-copy-to-vm.kde $RPM_BUILD_ROOT/usr/lib/qubes cp qubes_add_pendrive_script qubes_penctl qvm-copy-to-vm.kde $RPM_BUILD_ROOT/usr/lib/qubes
cp ../qrexec/qrexec_agent $RPM_BUILD_ROOT/usr/lib/qubes cp ../qrexec/qrexec_agent $RPM_BUILD_ROOT/usr/lib/qubes
cp dvm_file_editor $RPM_BUILD_ROOT/usr/lib/qubes cp dvm_file_editor qfile-agent $RPM_BUILD_ROOT/usr/lib/qubes
ln -s /usr/bin/qvm-open-in-dvm $RPM_BUILD_ROOT/usr/lib/qubes/qvm-dvm-transfer ln -s /usr/bin/qvm-open-in-dvm $RPM_BUILD_ROOT/usr/lib/qubes/qvm-dvm-transfer
cp ../common/meminfo-writer $RPM_BUILD_ROOT/usr/lib/qubes cp ../common/meminfo-writer $RPM_BUILD_ROOT/usr/lib/qubes
mkdir -p $RPM_BUILD_ROOT/%{kde_service_dir} mkdir -p $RPM_BUILD_ROOT/%{kde_service_dir}
@ -216,6 +216,7 @@ rm -rf $RPM_BUILD_ROOT
%attr(4755,root,root) /usr/lib/qubes/qubes_penctl %attr(4755,root,root) /usr/lib/qubes/qubes_penctl
/usr/lib/qubes/qubes_add_pendrive_script /usr/lib/qubes/qubes_add_pendrive_script
/usr/lib/qubes/qrexec_agent /usr/lib/qubes/qrexec_agent
/usr/lib/qubes/qfile-agent
/etc/udev/rules.d/qubes.rules /etc/udev/rules.d/qubes.rules
/etc/sysconfig/iptables /etc/sysconfig/iptables
/var/lib/qubes /var/lib/qubes