diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs.c b/src/protocols/rdp/guac_rdpdr/rdpdr_fs.c index 3f958ad5..9f1172b2 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs.c @@ -326,6 +326,52 @@ int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path, } +int guac_rdpdr_fs_read(guac_rdpdr_device* device, int file_id, int offset, + void* buffer, int length) { + + int bytes_read; + + guac_rdpdr_fs_file* file = guac_rdpdr_fs_get_file(device, file_id); + if (file == NULL) { + GUAC_RDP_DEBUG(1, "Read from bad file_id: %i", file_id); + return GUAC_RDPDR_FS_EINVAL; + } + + /* Attempt read */ + lseek(file->fd, offset, SEEK_SET); + bytes_read = read(file->fd, buffer, length); + + /* Translate errno on error */ + if (bytes_read < 0) + return guac_rdpdr_fs_get_errorcode(errno); + + return bytes_read; + +} + +int guac_rdpdr_fs_write(guac_rdpdr_device* device, int file_id, int offset, + void* buffer, int length) { + + int bytes_written; + + guac_rdpdr_fs_file* file = guac_rdpdr_fs_get_file(device, file_id); + if (file == NULL) { + GUAC_RDP_DEBUG(1, "Write to bad file_id: %i", file_id); + return GUAC_RDPDR_FS_EINVAL; + } + + /* Attempt write */ + lseek(file->fd, offset, SEEK_SET); + bytes_written = write(file->fd, buffer, length); + + /* Translate errno on error */ + if (bytes_written < 0) + return guac_rdpdr_fs_get_errorcode(errno); + + return bytes_written; + +} + int guac_rdpdr_fs_rename(guac_rdpdr_device* device, int file_id, const char* new_path) { diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs.h b/src/protocols/rdp/guac_rdpdr/rdpdr_fs.h index a7ca2b58..cd9d2c7f 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs.h +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs.h @@ -314,6 +314,22 @@ int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path, int access, int file_attributes, int create_disposition, int create_options); +/** + * Reads up to the given length of bytes from the given offset within the + * file having the given ID. Returns the number of bytes read, zero on EOF, + * and an error code if an error occurs. + */ +int guac_rdpdr_fs_read(guac_rdpdr_device* device, int file_id, int offset, + void* buffer, int length); + +/** + * Writes up to the given length of bytes from the given offset within the + * file having the given ID. Returns the number of bytes written, and an + * error code if an error occurs. + */ +int guac_rdpdr_fs_write(guac_rdpdr_device* device, int file_id, int offset, + void* buffer, int length); + /** * Renames (moves) the file with the given ID to the new path specified. * Returns zero on success, or an error code if an error occurs. diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c index 8c717aa4..b53d2e19 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c @@ -115,60 +115,35 @@ void guac_rdpdr_fs_process_read(guac_rdpdr_device* device, UINT32 length; UINT64 offset; char buffer[4096]; + int bytes_read; wStream* output_stream; - guac_rdpdr_fs_file* file; - - /* Get file */ - file = guac_rdpdr_fs_get_file(device, file_id); - if (file == NULL) - return; /* Read packet */ Stream_Read_UINT32(input_stream, length); Stream_Read_UINT64(input_stream, offset); - /* If file is a directory, fail */ - if (file->attributes & FILE_ATTRIBUTE_DIRECTORY) { - guac_client_log_error(device->rdpdr->client, - "Refusing to read directory as a file"); + /* Read no more than size of buffer */ + if (length > sizeof(buffer)) + length = sizeof(buffer); + /* Attempt read */ + bytes_read = guac_rdpdr_fs_read(device, file_id, offset, + buffer, length); + + /* If error, return invalid parameter */ + if (bytes_read < 0) { output_stream = guac_rdpdr_new_io_completion(device, completion_id, - STATUS_FILE_IS_A_DIRECTORY, 4); + guac_rdpdr_fs_get_status(bytes_read), 4); Stream_Write_UINT32(output_stream, 0); /* Length */ } - /* Otherwise, perform read */ + /* Otherwise, send bytes read */ else { - - int bytes_read; - - /* Read no more than size of buffer */ - if (length > sizeof(buffer)) - length = sizeof(buffer); - - /* Attempt read */ - lseek(file->fd, offset, SEEK_SET); - bytes_read = read(file->fd, buffer, length); - - /* If error, return invalid parameter */ - if (bytes_read < 0) { - guac_client_log_error(device->rdpdr->client, - "Unable to read from file: %s", strerror(errno)); - - output_stream = guac_rdpdr_new_io_completion(device, completion_id, - STATUS_INVALID_PARAMETER, 4); - Stream_Write_UINT32(output_stream, 0); /* Length */ - } - - /* Otherwise, send bytes read */ - else { - output_stream = guac_rdpdr_new_io_completion(device, completion_id, - STATUS_SUCCESS, 4+bytes_read); - Stream_Write_UINT32(output_stream, bytes_read); /* Length */ - Stream_Write(output_stream, buffer, bytes_read); /* ReadData */ - } - + output_stream = guac_rdpdr_new_io_completion(device, completion_id, + STATUS_SUCCESS, 4+bytes_read); + Stream_Write_UINT32(output_stream, bytes_read); /* Length */ + Stream_Write(output_stream, buffer, bytes_read); /* ReadData */ } svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream); @@ -180,60 +155,33 @@ void guac_rdpdr_fs_process_write(guac_rdpdr_device* device, UINT32 length; UINT64 offset; + int bytes_written; wStream* output_stream; - guac_rdpdr_fs_file* file; - - /* Get file */ - file = guac_rdpdr_fs_get_file(device, file_id); - if (file == NULL) - return; /* Read packet */ Stream_Read_UINT32(input_stream, length); Stream_Read_UINT64(input_stream, offset); Stream_Seek(input_stream, 20); /* Padding */ - /* If file is a directory, fail */ - if (file->attributes & FILE_ATTRIBUTE_DIRECTORY) { - guac_client_log_error(device->rdpdr->client, - "Refusing to write directory as a file"); + /* Attempt write */ + bytes_written = guac_rdpdr_fs_write(device, file_id, offset, + Stream_Pointer(input_stream), length); + /* If error, return invalid parameter */ + if (bytes_written < 0) { output_stream = guac_rdpdr_new_io_completion(device, completion_id, - STATUS_FILE_IS_A_DIRECTORY, 5); + guac_rdpdr_fs_get_status(bytes_written), 5); Stream_Write_UINT32(output_stream, 0); /* Length */ Stream_Write_UINT8(output_stream, 0); /* Padding */ } - /* Otherwise, perform write */ + /* Otherwise, send success */ else { - - int bytes_written; - - /* Attempt read */ - lseek(file->fd, offset, SEEK_SET); - bytes_written = write(file->fd, Stream_Pointer(input_stream), length); - - /* If error, return invalid parameter */ - if (bytes_written < 0) { - guac_client_log_error(device->rdpdr->client, - "Unable to write to file %i: %s", file->fd, - strerror(errno)); - - output_stream = guac_rdpdr_new_io_completion(device, completion_id, - STATUS_ACCESS_DENIED, 5); - Stream_Write_UINT32(output_stream, 0); /* Length */ - Stream_Write_UINT8(output_stream, 0); /* Padding */ - } - - /* Otherwise, send success */ - else { - output_stream = guac_rdpdr_new_io_completion(device, completion_id, - STATUS_SUCCESS, 5); - Stream_Write_UINT32(output_stream, bytes_written); /* Length */ - Stream_Write_UINT8(output_stream, 0); /* Padding */ - } - + output_stream = guac_rdpdr_new_io_completion(device, completion_id, + STATUS_SUCCESS, 5); + Stream_Write_UINT32(output_stream, bytes_written); /* Length */ + Stream_Write_UINT8(output_stream, 0); /* Padding */ } svc_plugin_send((rdpSvcPlugin*) device->rdpdr, output_stream);