summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/vdagent/file-xfers.c40
-rw-r--r--src/vdagentd/vdagentd.c7
2 files changed, 47 insertions, 0 deletions
diff --git a/src/vdagent/file-xfers.c b/src/vdagent/file-xfers.c
index fe762d7..af73d87 100644
--- a/src/vdagent/file-xfers.c
+++ b/src/vdagent/file-xfers.c
@@ -32,6 +32,7 @@
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
+#include <sys/statvfs.h>
#include <sys/types.h>
#include <spice/vd_agent.h>
#include <glib.h>
@@ -168,6 +169,17 @@ error:
return NULL;
}
+static uint64_t get_free_space_available(const char *path)
+{
+ struct statvfs stat;
+ if (statvfs(path, &stat) != 0) {
+ syslog(LOG_WARNING, "file-xfer: failed to get free space, statvfs error: %s",
+ strerror(errno));
+ return G_MAXUINT64;
+ }
+ return stat.f_bsize * stat.f_bavail;
+}
+
void vdagent_file_xfers_start(struct vdagent_file_xfers *xfers,
VDAgentFileXferStartMessage *msg)
{
@@ -175,6 +187,7 @@ void vdagent_file_xfers_start(struct vdagent_file_xfers *xfers,
char *dir = NULL, *path = NULL, *file_path = NULL;
struct stat st;
int i;
+ uint64_t free_space;
g_return_if_fail(xfers != NULL);
@@ -193,6 +206,33 @@ void vdagent_file_xfers_start(struct vdagent_file_xfers *xfers,
file_path = g_build_filename(xfers->save_dir, task->file_name, NULL);
+ free_space = get_free_space_available(xfers->save_dir);
+ if (task->file_size > free_space) {
+ gchar *free_space_str, *file_size_str;
+#if GLIB_CHECK_VERSION(2, 30, 0)
+ free_space_str = g_format_size(free_space);
+ file_size_str = g_format_size(task->file_size);
+#else
+ free_space_str = g_format_size_for_display(free_space);
+ file_size_str = g_format_size_for_display(task->file_size);
+#endif
+ syslog(LOG_ERR, "file-xfer: not enough free space (%s to copy, %s free)",
+ file_size_str, free_space_str);
+ g_free(free_space_str);
+ g_free(file_size_str);
+
+ udscs_write(xfers->vdagentd,
+ VDAGENTD_FILE_XFER_STATUS,
+ msg->id,
+ VD_AGENT_FILE_XFER_STATUS_NOT_ENOUGH_SPACE,
+ (uint8_t *)&free_space,
+ sizeof(free_space));
+ vdagent_file_xfer_task_free(task);
+ g_free(file_path);
+ g_free(dir);
+ return;
+ }
+
dir = g_path_get_dirname(file_path);
if (g_mkdir_with_parents(dir, S_IRWXU) == -1) {
syslog(LOG_ERR, "file-xfer: Failed to create dir %s", dir);
diff --git a/src/vdagentd/vdagentd.c b/src/vdagentd/vdagentd.c
index a0cee50..5373909 100644
--- a/src/vdagentd/vdagentd.c
+++ b/src/vdagentd/vdagentd.c
@@ -925,6 +925,13 @@ static void agent_read_complete(struct udscs_connection **connp,
case VDAGENTD_FILE_XFER_STATUS:{
/* header->arg1 = file xfer task id, header->arg2 = file xfer status */
switch (header->arg2) {
+ case VD_AGENT_FILE_XFER_STATUS_NOT_ENOUGH_SPACE: {
+ uint64_t free_space = GUINT64_TO_LE(*((uint64_t*)data));
+ send_file_xfer_status(virtio_port, "Not enough free space. Cancelling file-xfer %u",
+ header->arg1, header->arg2,
+ (uint8_t*)&free_space, sizeof(uint64_t));
+ break;
+ }
default:
send_file_xfer_status(virtio_port, NULL, header->arg1, header->arg2, NULL, 0);
}