[PATCH win-vdagent v2] Support file transfer for existing files

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Previously, if the user attempted to transfer a file that had the same
name as a file that already exists on the guest, we would just fail the
transfer. This patch tries to match the behavior of the linux vdagent
where we try to append an integer onto the name of the new file to make
it unique. For example, if you tried to transfer 'file.doc' to the guest
and that file already existed, it would try to create 'file (1).doc'
instead. If that also failed, it would attempt 'file (2).doc', etc, up
to 63.

Resolves: rhbz#1410181
Signed-off-by: Jonathon Jongsma <jjongsma@xxxxxxxxxx>
---
Changes since v1:
 - change from "file.doc (1)" to "file (1).doc"
 - retain debug output for other CreateFile errors

 vdagent/file_xfer.cpp | 50 ++++++++++++++++++++++++++++++++++++++++++++------
 1 file changed, 44 insertions(+), 6 deletions(-)

diff --git a/vdagent/file_xfer.cpp b/vdagent/file_xfer.cpp
index f763ed3..24eb00a 100644
--- a/vdagent/file_xfer.cpp
+++ b/vdagent/file_xfer.cpp
@@ -61,6 +61,7 @@ void FileXfer::handle_start(VDAgentFileXferStartMessage* start,
     HANDLE handle;
     AsUser as_user;
     int wlen;
+    int attempt = 0;
 
     status->id = start->id;
     status->result = VD_AGENT_FILE_XFER_STATUS_ERROR;
@@ -99,15 +100,52 @@ void FileXfer::handle_start(VDAgentFileXferStartMessage* start,
 
     file_path[wlen++] = TEXT('\\');
     file_path[wlen] = TEXT('\0');
-    if((wlen = MultiByteToWideChar(CP_UTF8, 0, file_name, -1, file_path + wlen, MAX_PATH - wlen)) == 0){
-        vd_printf("failed converting file_name:%s to WideChar", file_name);
-        return;
+
+    const int MAX_ATTEMPTS = 64; // matches behavior of linux vdagent
+    const size_t POSTFIX_LEN = 6; // up to 2 digits in parentheses and final NULL: " (xx)"
+    size_t name_len = strlen(file_name);
+    char *extension = strrchr(file_name, '.');
+
+    for (attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
+        char dest_filename[MAX_PATH];
+        if (attempt == 0) {
+            strcpy(dest_filename, file_name);
+        } else {
+            if (name_len + POSTFIX_LEN > MAX_PATH) {
+                vd_printf("failed creating %ls. Postfix makes name too long for the buffer.", file_path);
+                return;
+            }
+
+            int basename_len = (extension != NULL) ? (extension - file_name) : name_len;
+            memcpy(dest_filename, file_name, basename_len);
+            // append postfix
+            int postfix_len = snprintf(dest_filename + basename_len, POSTFIX_LEN, " (%d)", attempt);
+            if (extension != NULL) {
+                strcpy(dest_filename + basename_len + postfix_len, extension);
+            }
+        }
+        if((MultiByteToWideChar(CP_UTF8, 0, dest_filename, -1, file_path + wlen, MAX_PATH - wlen)) == 0){
+            vd_printf("failed converting file_name:%s to WideChar", dest_filename);
+            return;
+        }
+        handle = CreateFile(file_path, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
+        if (handle != INVALID_HANDLE_VALUE) {
+            break;
+        }
+
+        // If the file already exists, we can re-try with a new filename. If
+        // it's a different error, there's not much we can do.
+        if (GetLastError() != ERROR_FILE_EXISTS) {
+            vd_printf("Failed creating %ls %lu", file_path, GetLastError());
+            return;
+        }
     }
-    handle = CreateFile(file_path, GENERIC_WRITE, 0, NULL, CREATE_NEW, 0, NULL);
-    if (handle == INVALID_HANDLE_VALUE) {
-        vd_printf("failed creating %ls %lu", file_path, GetLastError());
+
+    if (attempt == MAX_ATTEMPTS) {
+        vd_printf("Failed creating %ls. More than 63 copies exist?", file_path);
         return;
     }
+
     task = new FileXferTask(handle, file_size, file_path);
     _tasks[start->id] = task;
     status->result = VD_AGENT_FILE_XFER_STATUS_CAN_SEND_DATA;
-- 
2.9.3

_______________________________________________
Spice-devel mailing list
Spice-devel@xxxxxxxxxxxxxxxxxxxxx
https://lists.freedesktop.org/mailman/listinfo/spice-devel




[Index of Archives]     [Linux ARM Kernel]     [Linux ARM]     [Linux Omap]     [Fedora ARM]     [IETF Annouce]     [Security]     [Bugtraq]     [Linux]     [Linux OMAP]     [Linux MIPS]     [ECOS]     [Asterisk Internet PBX]     [Linux API]     [Monitors]