[Spice-devel] [PATCH win-vdagent v2] Support file transfer for existing files
Pavel Grunt
pgrunt at redhat.com
Fri Apr 28 08:47:25 UTC 2017
On Thu, 2017-04-27 at 15:20 -0500, Jonathon Jongsma wrote:
> 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 at redhat.com>
> ---
> 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,
missing space^
> file_path + wlen, MAX_PATH - wlen)) == 0){
and here ^
> + 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;
looks good, ack
Pavel
More information about the Spice-devel
mailing list