Added qfile-agent
This commit is contained in:
		
							parent
							
								
									66bf0abb53
								
							
						
					
					
						commit
						b8d983cfa9
					
				@ -1,10 +1,12 @@
 | 
			
		||||
CC=gcc
 | 
			
		||||
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
 | 
			
		||||
	$(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
 | 
			
		||||
	$(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
 | 
			
		||||
	$(CC) -o qubes_penctl qubes_penctl.o -lxenstore
 | 
			
		||||
qubes_add_pendrive_script: qubes_add_pendrive_script.o
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										28
									
								
								appvm/copy_file.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								appvm/copy_file.c
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										18
									
								
								appvm/filecopy.h
									
									
									
									
									
										Normal 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
									
								
							
							
						
						
									
										201
									
								
								appvm/qfile-agent.c
									
									
									
									
									
										Normal 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, ¤t, datasize);
 | 
			
		||||
	client_flags = get_item(data, ¤t, datasize);
 | 
			
		||||
	notify_progress(0, 1);
 | 
			
		||||
	send_vmname(vmname);
 | 
			
		||||
	while ((entry = get_item(data, ¤t, 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;
 | 
			
		||||
}
 | 
			
		||||
@ -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
 | 
			
		||||
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 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 
 | 
			
		||||
cp ../common/meminfo-writer $RPM_BUILD_ROOT/usr/lib/qubes
 | 
			
		||||
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
 | 
			
		||||
/usr/lib/qubes/qubes_add_pendrive_script
 | 
			
		||||
/usr/lib/qubes/qrexec_agent
 | 
			
		||||
/usr/lib/qubes/qfile-agent
 | 
			
		||||
/etc/udev/rules.d/qubes.rules
 | 
			
		||||
/etc/sysconfig/iptables
 | 
			
		||||
/var/lib/qubes
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user