Separate RDP filesystem operations from RDPDR.

This commit is contained in:
Michael Jumper 2013-11-04 00:50:10 -08:00
parent 28c3c7d926
commit aacb726b66
16 changed files with 357 additions and 236 deletions

View File

@ -47,6 +47,7 @@ libguac_client_rdp_la_SOURCES = \
guac_handlers.c \ guac_handlers.c \
rdp_bitmap.c \ rdp_bitmap.c \
rdp_cliprdr.c \ rdp_cliprdr.c \
rdp_fs.c \
rdp_gdi.c \ rdp_gdi.c \
rdp_glyph.c \ rdp_glyph.c \
rdp_keymap_base.c \ rdp_keymap_base.c \
@ -64,7 +65,6 @@ guacsnd_sources = \
guac_rdpsnd/rdpsnd_service.c guac_rdpsnd/rdpsnd_service.c
guacdr_sources = \ guacdr_sources = \
guac_rdpdr/rdpdr_fs.c \
guac_rdpdr/rdpdr_fs_messages.c \ guac_rdpdr/rdpdr_fs_messages.c \
guac_rdpdr/rdpdr_fs_messages_dir_info.c \ guac_rdpdr/rdpdr_fs_messages_dir_info.c \
guac_rdpdr/rdpdr_fs_messages_file_info.c \ guac_rdpdr/rdpdr_fs_messages_file_info.c \
@ -73,15 +73,16 @@ guacdr_sources = \
guac_rdpdr/rdpdr_messages.c \ guac_rdpdr/rdpdr_messages.c \
guac_rdpdr/rdpdr_printer.c \ guac_rdpdr/rdpdr_printer.c \
guac_rdpdr/rdpdr_service.c \ guac_rdpdr/rdpdr_service.c \
rdp_fs.c \
unicode.c unicode.c
noinst_HEADERS = \ noinst_HEADERS = \
compat/client-cliprdr.h \ compat/client-cliprdr.h \
guac_rdpdr/rdpdr_fs.h \
guac_rdpdr/rdpdr_fs_messages.h \ guac_rdpdr/rdpdr_fs_messages.h \
guac_rdpdr/rdpdr_fs_messages_dir_info.h \ guac_rdpdr/rdpdr_fs_messages_dir_info.h \
guac_rdpdr/rdpdr_fs_messages_file_info.h \ guac_rdpdr/rdpdr_fs_messages_file_info.h \
guac_rdpdr/rdpdr_fs_messages_vol_info.h \ guac_rdpdr/rdpdr_fs_messages_vol_info.h \
guac_rdpdr/rdpdr_fs_service.h \
guac_rdpdr/rdpdr_messages.h \ guac_rdpdr/rdpdr_messages.h \
guac_rdpdr/rdpdr_printer.h \ guac_rdpdr/rdpdr_printer.h \
guac_rdpdr/rdpdr_service.h \ guac_rdpdr/rdpdr_service.h \
@ -94,11 +95,13 @@ noinst_HEADERS = \
guac_handlers.h \ guac_handlers.h \
rdp_bitmap.h \ rdp_bitmap.h \
rdp_cliprdr.h \ rdp_cliprdr.h \
rdp_fs.h \
rdp_gdi.h \ rdp_gdi.h \
rdp_glyph.h \ rdp_glyph.h \
rdp_keymap.h \ rdp_keymap.h \
rdp_pointer.h \ rdp_pointer.h \
rdp_settings.h \ rdp_settings.h \
rdp_status.h \
unicode.h unicode.h
# Add compatibility layer for WinPR if not available # Add compatibility layer for WinPR if not available

View File

@ -184,6 +184,12 @@ BOOL rdp_freerdp_pre_connect(freerdp* instance) {
} /* end if audio enabled */ } /* end if audio enabled */
/* Load filesystem if drive enabled */
if (guac_client_data->settings.drive_enabled) {
guac_client_data->filesystem =
guac_rdp_fs_alloc(guac_client_data->settings.drive_path);
}
/* If RDPDR required, load it */ /* If RDPDR required, load it */
if (guac_client_data->settings.printing_enabled if (guac_client_data->settings.printing_enabled
|| guac_client_data->settings.drive_enabled) { || guac_client_data->settings.drive_enabled) {
@ -546,7 +552,6 @@ int guac_client_init(guac_client* client, int argc, char** argv) {
guac_client_data->settings.drive_enabled = guac_client_data->settings.drive_enabled =
(strcmp(argv[IDX_ENABLE_DRIVE], "true") == 0); (strcmp(argv[IDX_ENABLE_DRIVE], "true") == 0);
/* Drive enable/disable */
guac_client_data->settings.drive_path = strdup(argv[IDX_DRIVE_PATH]); guac_client_data->settings.drive_path = strdup(argv[IDX_DRIVE_PATH]);
/* Store client data */ /* Store client data */
@ -556,6 +561,7 @@ int guac_client_init(guac_client* client, int argc, char** argv) {
guac_client_data->current_surface = GUAC_DEFAULT_LAYER; guac_client_data->current_surface = GUAC_DEFAULT_LAYER;
guac_client_data->clipboard = NULL; guac_client_data->clipboard = NULL;
guac_client_data->audio = NULL; guac_client_data->audio = NULL;
guac_client_data->filesystem = NULL;
/* Main socket needs to be threadsafe */ /* Main socket needs to be threadsafe */
guac_socket_require_threadsafe(client->socket); guac_socket_require_threadsafe(client->socket);

View File

@ -48,6 +48,7 @@
#include <guacamole/client.h> #include <guacamole/client.h>
#include <guacamole/audio.h> #include <guacamole/audio.h>
#include "rdp_fs.h"
#include "rdp_keymap.h" #include "rdp_keymap.h"
#include "rdp_settings.h" #include "rdp_settings.h"
@ -168,6 +169,11 @@ typedef struct rdp_guac_client_data {
*/ */
guac_audio_stream* audio; guac_audio_stream* audio;
/**
* The filesystem being shared, if any.
*/
guac_rdp_fs* filesystem;
/** /**
* Lock which is locked and unlocked for each RDP message. * Lock which is locked and unlocked for each RDP message.
*/ */

View File

@ -95,6 +95,10 @@ int rdp_guac_client_free_handler(guac_client* client) {
cache_free(rdp_inst->context->cache); cache_free(rdp_inst->context->cache);
freerdp_free(rdp_inst); freerdp_free(rdp_inst);
/* Clean up filesystem, if allocated */
if (guac_client_data->filesystem != NULL)
guac_rdp_fs_free(guac_client_data->filesystem);
/* Free client data */ /* Free client data */
cairo_surface_destroy(guac_client_data->opaque_glyph_surface); cairo_surface_destroy(guac_client_data->opaque_glyph_surface);
cairo_surface_destroy(guac_client_data->trans_glyph_surface); cairo_surface_destroy(guac_client_data->trans_glyph_surface);

View File

@ -44,7 +44,8 @@
#include <guacamole/pool.h> #include <guacamole/pool.h>
#include <errno.h> #include <errno.h>
#include "rdpdr_fs.h" #include "rdp_fs.h"
#include "rdp_status.h"
#include "rdpdr_fs_messages.h" #include "rdpdr_fs_messages.h"
#include "rdpdr_fs_messages_vol_info.h" #include "rdpdr_fs_messages_vol_info.h"
#include "rdpdr_fs_messages_file_info.h" #include "rdpdr_fs_messages_file_info.h"
@ -65,7 +66,7 @@ void guac_rdpdr_fs_process_create(guac_rdpdr_device* device,
int desired_access, file_attributes; int desired_access, file_attributes;
int create_disposition, create_options, path_length; int create_disposition, create_options, path_length;
char path[GUAC_RDPDR_FS_MAX_PATH]; char path[GUAC_RDP_FS_MAX_PATH];
/* Read "create" information */ /* Read "create" information */
Stream_Read_UINT32(input_stream, desired_access); Stream_Read_UINT32(input_stream, desired_access);
@ -83,7 +84,8 @@ void guac_rdpdr_fs_process_create(guac_rdpdr_device* device,
path, path_length/2 - 1); path, path_length/2 - 1);
/* Open file */ /* Open file */
file_id = guac_rdpdr_fs_open(device, path, desired_access, file_attributes, file_id = guac_rdp_fs_open((guac_rdp_fs*) device->data, path,
desired_access, file_attributes,
create_disposition, create_options); create_disposition, create_options);
/* If an error occurred, notify server */ /* If an error occurred, notify server */
@ -92,7 +94,7 @@ void guac_rdpdr_fs_process_create(guac_rdpdr_device* device,
"File open refused (%i): \"%s\"", file_id, path); "File open refused (%i): \"%s\"", file_id, path);
output_stream = guac_rdpdr_new_io_completion(device, completion_id, output_stream = guac_rdpdr_new_io_completion(device, completion_id,
guac_rdpdr_fs_get_status(file_id), 5); guac_rdp_fs_get_status(file_id), 5);
Stream_Write_UINT32(output_stream, 0); /* fileId */ Stream_Write_UINT32(output_stream, 0); /* fileId */
Stream_Write_UINT8(output_stream, 0); /* information */ Stream_Write_UINT8(output_stream, 0); /* information */
} }
@ -128,13 +130,13 @@ void guac_rdpdr_fs_process_read(guac_rdpdr_device* device,
length = sizeof(buffer); length = sizeof(buffer);
/* Attempt read */ /* Attempt read */
bytes_read = guac_rdpdr_fs_read(device, file_id, offset, bytes_read = guac_rdp_fs_read((guac_rdp_fs*) device->data, file_id, offset,
buffer, length); buffer, length);
/* If error, return invalid parameter */ /* If error, return invalid parameter */
if (bytes_read < 0) { if (bytes_read < 0) {
output_stream = guac_rdpdr_new_io_completion(device, completion_id, output_stream = guac_rdpdr_new_io_completion(device, completion_id,
guac_rdpdr_fs_get_status(bytes_read), 4); guac_rdp_fs_get_status(bytes_read), 4);
Stream_Write_UINT32(output_stream, 0); /* Length */ Stream_Write_UINT32(output_stream, 0); /* Length */
} }
@ -165,13 +167,13 @@ void guac_rdpdr_fs_process_write(guac_rdpdr_device* device,
Stream_Seek(input_stream, 20); /* Padding */ Stream_Seek(input_stream, 20); /* Padding */
/* Attempt write */ /* Attempt write */
bytes_written = guac_rdpdr_fs_write(device, file_id, offset, bytes_written = guac_rdp_fs_write((guac_rdp_fs*) device->data, file_id,
Stream_Pointer(input_stream), length); offset, Stream_Pointer(input_stream), length);
/* If error, return invalid parameter */ /* If error, return invalid parameter */
if (bytes_written < 0) { if (bytes_written < 0) {
output_stream = guac_rdpdr_new_io_completion(device, completion_id, output_stream = guac_rdpdr_new_io_completion(device, completion_id,
guac_rdpdr_fs_get_status(bytes_written), 5); guac_rdp_fs_get_status(bytes_written), 5);
Stream_Write_UINT32(output_stream, 0); /* Length */ Stream_Write_UINT32(output_stream, 0); /* Length */
Stream_Write_UINT8(output_stream, 0); /* Padding */ Stream_Write_UINT8(output_stream, 0); /* Padding */
} }
@ -194,7 +196,7 @@ void guac_rdpdr_fs_process_close(guac_rdpdr_device* device,
wStream* output_stream; wStream* output_stream;
/* Close file */ /* Close file */
guac_rdpdr_fs_close(device, file_id); guac_rdp_fs_close((guac_rdp_fs*) device->data, file_id);
output_stream = guac_rdpdr_new_io_completion(device, completion_id, output_stream = guac_rdpdr_new_io_completion(device, completion_id,
STATUS_SUCCESS, 4); STATUS_SUCCESS, 4);
@ -354,14 +356,14 @@ void guac_rdpdr_fs_process_query_directory(guac_rdpdr_device* device, wStream* i
wStream* output_stream; wStream* output_stream;
guac_rdpdr_fs_file* file; guac_rdp_fs_file* file;
int fs_information_class, initial_query; int fs_information_class, initial_query;
int path_length; int path_length;
const char* entry_name; const char* entry_name;
/* Get file */ /* Get file */
file = guac_rdpdr_fs_get_file(device, file_id); file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id);
if (file == NULL) if (file == NULL)
return; return;
@ -384,22 +386,23 @@ void guac_rdpdr_fs_process_query_directory(guac_rdpdr_device* device, wStream* i
} }
/* Find first matching entry in directory */ /* Find first matching entry in directory */
while ((entry_name = guac_rdpdr_fs_read_dir(device, file_id)) != NULL) { while ((entry_name = guac_rdp_fs_read_dir((guac_rdp_fs*) device->data,
file_id)) != NULL) {
/* Convert to absolute path */ /* Convert to absolute path */
char entry_path[GUAC_RDPDR_FS_MAX_PATH]; char entry_path[GUAC_RDP_FS_MAX_PATH];
if (guac_rdpdr_fs_convert_path(file->absolute_path, if (guac_rdp_fs_convert_path(file->absolute_path,
entry_name, entry_path) == 0) { entry_name, entry_path) == 0) {
int entry_file_id; int entry_file_id;
/* Pattern defined and match fails, continue with next file */ /* Pattern defined and match fails, continue with next file */
if (guac_rdpdr_fs_matches(entry_path, file->dir_pattern)) if (guac_rdp_fs_matches(entry_path, file->dir_pattern))
continue; continue;
/* Open directory entry */ /* Open directory entry */
entry_file_id = guac_rdpdr_fs_open(device, entry_path, entry_file_id = guac_rdp_fs_open((guac_rdp_fs*) device->data,
ACCESS_FILE_READ_DATA, 0, DISP_FILE_OPEN, 0); entry_path, ACCESS_FILE_READ_DATA, 0, DISP_FILE_OPEN, 0);
if (entry_file_id >= 0) { if (entry_file_id >= 0) {
@ -432,7 +435,7 @@ void guac_rdpdr_fs_process_query_directory(guac_rdpdr_device* device, wStream* i
fs_information_class); fs_information_class);
} }
guac_rdpdr_fs_close(device, entry_file_id); guac_rdp_fs_close((guac_rdp_fs*) device->data, entry_file_id);
return; return;
} /* end if file exists */ } /* end if file exists */

View File

@ -45,7 +45,8 @@
#include "rdpdr_service.h" #include "rdpdr_service.h"
#include "rdpdr_messages.h" #include "rdpdr_messages.h"
#include "rdpdr_fs.h" #include "rdp_fs.h"
#include "rdp_status.h"
#include "unicode.h" #include "unicode.h"
void guac_rdpdr_fs_process_query_directory_info(guac_rdpdr_device* device, void guac_rdpdr_fs_process_query_directory_info(guac_rdpdr_device* device,
@ -63,7 +64,7 @@ void guac_rdpdr_fs_process_query_full_directory_info(guac_rdpdr_device* device,
void guac_rdpdr_fs_process_query_both_directory_info(guac_rdpdr_device* device, void guac_rdpdr_fs_process_query_both_directory_info(guac_rdpdr_device* device,
const char* entry_name, int file_id, int completion_id) { const char* entry_name, int file_id, int completion_id) {
guac_rdpdr_fs_file* file; guac_rdp_fs_file* file;
wStream* output_stream = Stream_New(NULL, 256); wStream* output_stream = Stream_New(NULL, 256);
int length = guac_utf8_strlen(entry_name); int length = guac_utf8_strlen(entry_name);
@ -73,7 +74,7 @@ void guac_rdpdr_fs_process_query_both_directory_info(guac_rdpdr_device* device,
guac_rdp_utf8_to_utf16((const unsigned char*) entry_name, (char*) utf16_entry_name, length); guac_rdp_utf8_to_utf16((const unsigned char*) entry_name, (char*) utf16_entry_name, length);
/* Get file */ /* Get file */
file = guac_rdpdr_fs_get_file(device, file_id); file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id);
if (file == NULL) if (file == NULL)
return; return;

View File

@ -44,7 +44,8 @@
#include <guacamole/pool.h> #include <guacamole/pool.h>
#include "rdpdr_messages.h" #include "rdpdr_messages.h"
#include "rdpdr_fs.h" #include "rdp_fs.h"
#include "rdp_status.h"
#include "rdpdr_service.h" #include "rdpdr_service.h"
#include "client.h" #include "client.h"
#include "debug.h" #include "debug.h"
@ -57,10 +58,10 @@ void guac_rdpdr_fs_process_query_basic_info(guac_rdpdr_device* device, wStream*
int file_id, int completion_id) { int file_id, int completion_id) {
wStream* output_stream; wStream* output_stream;
guac_rdpdr_fs_file* file; guac_rdp_fs_file* file;
/* Get file */ /* Get file */
file = guac_rdpdr_fs_get_file(device, file_id); file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id);
if (file == NULL) if (file == NULL)
return; return;
@ -86,11 +87,11 @@ void guac_rdpdr_fs_process_query_standard_info(guac_rdpdr_device* device, wStrea
int file_id, int completion_id) { int file_id, int completion_id) {
wStream* output_stream; wStream* output_stream;
guac_rdpdr_fs_file* file; guac_rdp_fs_file* file;
BOOL is_directory = FALSE; BOOL is_directory = FALSE;
/* Get file */ /* Get file */
file = guac_rdpdr_fs_get_file(device, file_id); file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id);
if (file == NULL) if (file == NULL)
return; return;
@ -119,10 +120,10 @@ void guac_rdpdr_fs_process_query_attribute_tag_info(guac_rdpdr_device* device,
wStream* input_stream, int file_id, int completion_id) { wStream* input_stream, int file_id, int completion_id) {
wStream* output_stream; wStream* output_stream;
guac_rdpdr_fs_file* file; guac_rdp_fs_file* file;
/* Get file */ /* Get file */
file = guac_rdpdr_fs_get_file(device, file_id); file = guac_rdp_fs_get_file((guac_rdp_fs*) device->data, file_id);
if (file == NULL) if (file == NULL)
return; return;
@ -147,7 +148,7 @@ void guac_rdpdr_fs_process_set_rename_info(guac_rdpdr_device* device,
int result; int result;
int filename_length; int filename_length;
wStream* output_stream; wStream* output_stream;
char destination_path[GUAC_RDPDR_FS_MAX_PATH]; char destination_path[GUAC_RDP_FS_MAX_PATH];
/* Read structure */ /* Read structure */
Stream_Seek_UINT8(input_stream); /* ReplaceIfExists */ Stream_Seek_UINT8(input_stream); /* ReplaceIfExists */
@ -159,10 +160,11 @@ void guac_rdpdr_fs_process_set_rename_info(guac_rdpdr_device* device,
destination_path, filename_length/2); destination_path, filename_length/2);
/* Perform rename */ /* Perform rename */
result = guac_rdpdr_fs_rename(device, file_id, destination_path); result = guac_rdp_fs_rename((guac_rdp_fs*) device->data, file_id,
destination_path);
if (result < 0) if (result < 0)
output_stream = guac_rdpdr_new_io_completion(device, output_stream = guac_rdpdr_new_io_completion(device,
completion_id, guac_rdpdr_fs_get_status(result), 4); completion_id, guac_rdp_fs_get_status(result), 4);
else else
output_stream = guac_rdpdr_new_io_completion(device, output_stream = guac_rdpdr_new_io_completion(device,
completion_id, STATUS_SUCCESS, 4); completion_id, STATUS_SUCCESS, 4);

View File

@ -44,7 +44,8 @@
#include <guacamole/pool.h> #include <guacamole/pool.h>
#include "rdpdr_messages.h" #include "rdpdr_messages.h"
#include "rdpdr_fs.h" #include "rdp_fs.h"
#include "rdp_status.h"
#include "rdpdr_service.h" #include "rdpdr_service.h"
#include "client.h" #include "client.h"
#include "unicode.h" #include "unicode.h"
@ -91,7 +92,7 @@ void guac_rdpdr_fs_process_query_attribute_info(guac_rdpdr_device* device, wStre
Stream_Write_UINT32(output_stream, 12 + GUAC_FILESYSTEM_NAME_LENGTH); Stream_Write_UINT32(output_stream, 12 + GUAC_FILESYSTEM_NAME_LENGTH);
Stream_Write_UINT32(output_stream, FILE_UNICODE_ON_DISK); /* FileSystemAttributes */ Stream_Write_UINT32(output_stream, FILE_UNICODE_ON_DISK); /* FileSystemAttributes */
Stream_Write_UINT32(output_stream, GUAC_RDPDR_FS_MAX_PATH ); /* MaximumComponentNameLength */ Stream_Write_UINT32(output_stream, GUAC_RDP_FS_MAX_PATH ); /* MaximumComponentNameLength */
Stream_Write_UINT32(output_stream, GUAC_FILESYSTEM_NAME_LENGTH); Stream_Write_UINT32(output_stream, GUAC_FILESYSTEM_NAME_LENGTH);
Stream_Write(output_stream, GUAC_FILESYSTEM_NAME, Stream_Write(output_stream, GUAC_FILESYSTEM_NAME,
GUAC_FILESYSTEM_NAME_LENGTH); GUAC_FILESYSTEM_NAME_LENGTH);

View File

@ -43,7 +43,7 @@
#include <guacamole/pool.h> #include <guacamole/pool.h>
#include "rdpdr_fs.h" #include "rdp_fs.h"
#include "rdpdr_fs_messages.h" #include "rdpdr_fs_messages.h"
#include "rdpdr_messages.h" #include "rdpdr_messages.h"
#include "rdpdr_service.h" #include "rdpdr_service.h"
@ -144,14 +144,11 @@ static void guac_rdpdr_device_fs_iorequest_handler(guac_rdpdr_device* device,
} }
static void guac_rdpdr_device_fs_free_handler(guac_rdpdr_device* device) { static void guac_rdpdr_device_fs_free_handler(guac_rdpdr_device* device) {
guac_rdpdr_fs_data* data = (guac_rdpdr_fs_data*) device->data;
guac_pool_free(data->file_id_pool);
free(data);
} }
void guac_rdpdr_register_fs(guac_rdpdrPlugin* rdpdr) { void guac_rdpdr_register_fs(guac_rdpdrPlugin* rdpdr) {
guac_rdpdr_fs_data* data; rdp_guac_client_data* data = (rdp_guac_client_data*) rdpdr->client->data;
int id = rdpdr->devices_registered++; int id = rdpdr->devices_registered++;
/* Get new device */ /* Get new device */
@ -168,9 +165,7 @@ void guac_rdpdr_register_fs(guac_rdpdrPlugin* rdpdr) {
device->free_handler = guac_rdpdr_device_fs_free_handler; device->free_handler = guac_rdpdr_device_fs_free_handler;
/* Init data */ /* Init data */
data = device->data = malloc(sizeof(guac_rdpdr_fs_data)); device->data = data->filesystem;
data->file_id_pool = guac_pool_alloc(0);
data->open_files = 0;
} }

View File

@ -0,0 +1,63 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is libguac-client-rdp.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __GUAC_RDPDR_FS_H
#define __GUAC_RDPDR_FS_H
/**
* Functions and macros specific to filesystem handling and initialization
* independent of RDP. The functions here may deal with the RDPDR device
* directly, but their semantics must not deal with RDP protocol messaging.
* Functions here represent a virtual Windows-style filesystem on top of UNIX
* system calls and structures, using the guac_rdpdr_device structure as a home
* for common data.
*
* @file rdpdr_fs.h
*/
#include <guacamole/pool.h>
#include "rdpdr_service.h"
/**
* Registers a new filesystem device within the RDPDR plugin. This must be done
* before RDPDR connection finishes.
*/
void guac_rdpdr_register_fs(guac_rdpdrPlugin* rdpdr);
#endif

View File

@ -198,30 +198,6 @@
#define IRP_MN_QUERY_DIRECTORY 0x00000001 #define IRP_MN_QUERY_DIRECTORY 0x00000001
#define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x00000002 #define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x00000002
/*
* Status constants.
*/
#define STATUS_SUCCESS 0x00000000
#define STATUS_NO_MORE_FILES 0x80000006
#define STATUS_DEVICE_OFF_LINE 0x80000010
#define STATUS_NOT_IMPLEMENTED 0xC0000002
#define STATUS_INVALID_PARAMETER 0xC000000D
#define STATUS_NO_SUCH_FILE 0xC000000F
#define STATUS_END_OF_FILE 0xC0000011
#define STATUS_ACCESS_DENIED 0xC0000022
#define STATUS_OBJECT_NAME_COLLISION 0xC0000035
#define STATUS_DISK_FULL 0xC000007F
#define STATUS_FILE_INVALID 0xC0000098
#define STATUS_FILE_IS_A_DIRECTORY 0xC00000BA
#define STATUS_NOT_SUPPORTED 0xC00000BB
#define STATUS_NOT_A_DIRECTORY 0xC0000103
#define STATUS_TOO_MANY_OPENED_FILES 0xC000011F
#define STATUS_CANNOT_DELETE 0xC0000121
#define STATUS_FILE_DELETED 0xC0000123
#define STATUS_FILE_CLOSED 0xC0000128
#define STATUS_FILE_SYSTEM_LIMITATION 0xC0000427
#define STATUS_FILE_TOO_LARGE 0xC0000904
/* /*
* Volume information constants. * Volume information constants.
*/ */

View File

@ -11,6 +11,7 @@
#include <guacamole/protocol.h> #include <guacamole/protocol.h>
#include "rdp_status.h"
#include "rdpdr_messages.h" #include "rdpdr_messages.h"
#include "rdpdr_printer.h" #include "rdpdr_printer.h"
#include "rdpdr_service.h" #include "rdpdr_service.h"

View File

@ -54,7 +54,7 @@
#include "rdpdr_service.h" #include "rdpdr_service.h"
#include "rdpdr_messages.h" #include "rdpdr_messages.h"
#include "rdpdr_printer.h" #include "rdpdr_printer.h"
#include "rdpdr_fs.h" #include "rdpdr_fs_service.h"
#include "client.h" #include "client.h"

View File

@ -35,6 +35,8 @@
* *
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#include <stdlib.h>
#include <string.h>
#include <unistd.h> #include <unistd.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
@ -43,43 +45,46 @@
#include <fnmatch.h> #include <fnmatch.h>
#include <errno.h> #include <errno.h>
#ifdef ENABLE_WINPR
#include <winpr/stream.h>
#else
#include "compat/winpr-stream.h"
#endif
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <guacamole/pool.h> #include <guacamole/pool.h>
#include "rdpdr_messages.h" #include "rdp_fs.h"
#include "rdpdr_fs.h" #include "rdp_status.h"
#include "rdpdr_service.h"
#include "client.h"
#include "debug.h" #include "debug.h"
#include "unicode.h" #include "unicode.h"
#include <freerdp/utils/svc_plugin.h> guac_rdp_fs* guac_rdp_fs_alloc(const char* drive_path) {
guac_rdp_fs* fs = malloc(sizeof(guac_rdp_fs));
fs->drive_path = strdup(drive_path);
fs->file_id_pool = guac_pool_alloc(0);
fs->open_files = 0;
return fs;
}
void guac_rdp_fs_free(guac_rdp_fs* fs) {
guac_pool_free(fs->file_id_pool);
free(fs->drive_path);
free(fs);
}
/** /**
* Translates an absolute Windows virtual_path to an absolute virtual_path * Translates an absolute Windows virtual_path to an absolute virtual_path
* which is within the "drive virtual_path" specified in the connection * which is within the "drive virtual_path" specified in the connection
* settings. * settings.
*/ */
static void __guac_rdpdr_fs_translate_path(guac_rdpdr_device* device, static void __guac_rdp_fs_translate_path(guac_rdp_fs* fs,
const char* virtual_path, char* real_path) { const char* virtual_path, char* real_path) {
/* Get drive path */ /* Get drive path */
rdp_guac_client_data* client_data = (rdp_guac_client_data*) device->rdpdr->client->data; char* drive_path = fs->drive_path;
char* drive_path = client_data->settings.drive_path;
int i; int i;
/* Start with path from settings */ /* Start with path from settings */
for (i=0; i<GUAC_RDPDR_FS_MAX_PATH-1; i++) { for (i=0; i<GUAC_RDP_FS_MAX_PATH-1; i++) {
/* Break on end-of-string */ /* Break on end-of-string */
char c = *(drive_path++); char c = *(drive_path++);
@ -92,7 +97,7 @@ static void __guac_rdpdr_fs_translate_path(guac_rdpdr_device* device,
} }
/* Translate path */ /* Translate path */
for (; i<GUAC_RDPDR_FS_MAX_PATH-1; i++) { for (; i<GUAC_RDP_FS_MAX_PATH-1; i++) {
/* Stop at end of string */ /* Stop at end of string */
char c = *(virtual_path++); char c = *(virtual_path++);
@ -113,56 +118,55 @@ static void __guac_rdpdr_fs_translate_path(guac_rdpdr_device* device,
} }
int guac_rdpdr_fs_get_errorcode(int err) { int guac_rdp_fs_get_errorcode(int err) {
/* Translate errno codes to GUAC_RDPDR_FS codes */ /* Translate errno codes to GUAC_RDP_FS codes */
if (err == ENFILE) return GUAC_RDPDR_FS_ENFILE; if (err == ENFILE) return GUAC_RDP_FS_ENFILE;
if (err == ENOENT) return GUAC_RDPDR_FS_ENOENT; if (err == ENOENT) return GUAC_RDP_FS_ENOENT;
if (err == ENOTDIR) return GUAC_RDPDR_FS_ENOTDIR; if (err == ENOTDIR) return GUAC_RDP_FS_ENOTDIR;
if (err == ENOSPC) return GUAC_RDPDR_FS_ENOSPC; if (err == ENOSPC) return GUAC_RDP_FS_ENOSPC;
if (err == EISDIR) return GUAC_RDPDR_FS_EISDIR; if (err == EISDIR) return GUAC_RDP_FS_EISDIR;
if (err == EACCES) return GUAC_RDPDR_FS_EACCES; if (err == EACCES) return GUAC_RDP_FS_EACCES;
if (err == EEXIST) return GUAC_RDPDR_FS_EEXIST; if (err == EEXIST) return GUAC_RDP_FS_EEXIST;
if (err == EINVAL) return GUAC_RDPDR_FS_EINVAL; if (err == EINVAL) return GUAC_RDP_FS_EINVAL;
if (err == ENOSYS) return GUAC_RDPDR_FS_ENOSYS; if (err == ENOSYS) return GUAC_RDP_FS_ENOSYS;
if (err == ENOTSUP) return GUAC_RDPDR_FS_ENOTSUP; if (err == ENOTSUP) return GUAC_RDP_FS_ENOTSUP;
/* Default to invalid parameter */ /* Default to invalid parameter */
return GUAC_RDPDR_FS_EINVAL; return GUAC_RDP_FS_EINVAL;
} }
int guac_rdpdr_fs_get_status(int err) { int guac_rdp_fs_get_status(int err) {
/* Translate GUAC_RDPDR_FS error code to RDPDR status code */ /* Translate GUAC_RDP_FS error code to RDPDR status code */
if (err == GUAC_RDPDR_FS_ENFILE) return STATUS_NO_MORE_FILES; if (err == GUAC_RDP_FS_ENFILE) return STATUS_NO_MORE_FILES;
if (err == GUAC_RDPDR_FS_ENOENT) return STATUS_NO_SUCH_FILE; if (err == GUAC_RDP_FS_ENOENT) return STATUS_NO_SUCH_FILE;
if (err == GUAC_RDPDR_FS_ENOTDIR) return STATUS_NOT_A_DIRECTORY; if (err == GUAC_RDP_FS_ENOTDIR) return STATUS_NOT_A_DIRECTORY;
if (err == GUAC_RDPDR_FS_ENOSPC) return STATUS_DISK_FULL; if (err == GUAC_RDP_FS_ENOSPC) return STATUS_DISK_FULL;
if (err == GUAC_RDPDR_FS_EISDIR) return STATUS_FILE_IS_A_DIRECTORY; if (err == GUAC_RDP_FS_EISDIR) return STATUS_FILE_IS_A_DIRECTORY;
if (err == GUAC_RDPDR_FS_EACCES) return STATUS_ACCESS_DENIED; if (err == GUAC_RDP_FS_EACCES) return STATUS_ACCESS_DENIED;
if (err == GUAC_RDPDR_FS_EEXIST) return STATUS_OBJECT_NAME_COLLISION; if (err == GUAC_RDP_FS_EEXIST) return STATUS_OBJECT_NAME_COLLISION;
if (err == GUAC_RDPDR_FS_EINVAL) return STATUS_INVALID_PARAMETER; if (err == GUAC_RDP_FS_EINVAL) return STATUS_INVALID_PARAMETER;
if (err == GUAC_RDPDR_FS_ENOSYS) return STATUS_NOT_IMPLEMENTED; if (err == GUAC_RDP_FS_ENOSYS) return STATUS_NOT_IMPLEMENTED;
if (err == GUAC_RDPDR_FS_ENOTSUP) return STATUS_NOT_SUPPORTED; if (err == GUAC_RDP_FS_ENOTSUP) return STATUS_NOT_SUPPORTED;
/* Default to invalid parameter */ /* Default to invalid parameter */
return STATUS_INVALID_PARAMETER; return STATUS_INVALID_PARAMETER;
} }
int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path, int guac_rdp_fs_open(guac_rdp_fs* fs, const char* path,
int access, int file_attributes, int create_disposition, int access, int file_attributes, int create_disposition,
int create_options) { int create_options) {
guac_rdpdr_fs_data* data = (guac_rdpdr_fs_data*) device->data; char real_path[GUAC_RDP_FS_MAX_PATH];
char real_path[GUAC_RDPDR_FS_MAX_PATH]; char normalized_path[GUAC_RDP_FS_MAX_PATH];
char normalized_path[GUAC_RDPDR_FS_MAX_PATH];
struct stat file_stat; struct stat file_stat;
int fd; int fd;
int file_id; int file_id;
guac_rdpdr_fs_file* file; guac_rdp_fs_file* file;
int flags = 0; int flags = 0;
@ -172,9 +176,9 @@ int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path,
create_options); create_options);
/* If no files available, return too many open */ /* If no files available, return too many open */
if (data->open_files >= GUAC_RDPDR_FS_MAX_FILES) { if (fs->open_files >= GUAC_RDP_FS_MAX_FILES) {
GUAC_RDP_DEBUG(1, "%s", "Failure - too many open files."); GUAC_RDP_DEBUG(1, "%s", "Failure - too many open files.");
return GUAC_RDPDR_FS_ENFILE; return GUAC_RDP_FS_ENFILE;
} }
/* If path empty, transform to root path */ /* If path empty, transform to root path */
@ -184,7 +188,7 @@ int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path,
/* If path is relative, the file does not exist */ /* If path is relative, the file does not exist */
else if (path[0] != '\\') { else if (path[0] != '\\') {
GUAC_RDP_DEBUG(1, "Failure - path \"%s\" is relative.", path); GUAC_RDP_DEBUG(1, "Failure - path \"%s\" is relative.", path);
return GUAC_RDPDR_FS_ENOENT; return GUAC_RDP_FS_ENOENT;
} }
/* Translate access into flags */ /* Translate access into flags */
@ -203,16 +207,16 @@ int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path,
flags |= O_APPEND; flags |= O_APPEND;
/* Normalize path, return no-such-file if invalid */ /* Normalize path, return no-such-file if invalid */
if (guac_rdpdr_fs_normalize_path(path, normalized_path)) { if (guac_rdp_fs_normalize_path(path, normalized_path)) {
GUAC_RDP_DEBUG(1, "Normalization of path \"%s\" failed.", path); GUAC_RDP_DEBUG(1, "Normalization of path \"%s\" failed.", path);
return GUAC_RDPDR_FS_ENOENT; return GUAC_RDP_FS_ENOENT;
} }
GUAC_RDP_DEBUG(2, "Normalized path \"%s\" to \"%s\".", GUAC_RDP_DEBUG(2, "Normalized path \"%s\" to \"%s\".",
path, normalized_path); path, normalized_path);
/* Translate normalized path to real path */ /* Translate normalized path to real path */
__guac_rdpdr_fs_translate_path(device, normalized_path, real_path); __guac_rdp_fs_translate_path(fs, normalized_path, real_path);
GUAC_RDP_DEBUG(2, "Translated path \"%s\" to \"%s\".", GUAC_RDP_DEBUG(2, "Translated path \"%s\" to \"%s\".",
normalized_path, real_path); normalized_path, real_path);
@ -252,7 +256,7 @@ int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path,
/* Unrecognised disposition */ /* Unrecognised disposition */
default: default:
return GUAC_RDPDR_FS_ENOSYS; return GUAC_RDP_FS_ENOSYS;
} }
@ -261,7 +265,7 @@ int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path,
if (mkdir(real_path, S_IRWXU)) { if (mkdir(real_path, S_IRWXU)) {
GUAC_RDP_DEBUG(1, "mkdir() failed: %s", strerror(errno)); GUAC_RDP_DEBUG(1, "mkdir() failed: %s", strerror(errno));
return guac_rdpdr_fs_get_errorcode(errno); return guac_rdp_fs_get_errorcode(errno);
} }
/* Unset O_CREAT and O_EXCL as directory must exist before open() */ /* Unset O_CREAT and O_EXCL as directory must exist before open() */
@ -273,12 +277,12 @@ int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path,
fd = open(real_path, flags, S_IRUSR | S_IWUSR); fd = open(real_path, flags, S_IRUSR | S_IWUSR);
if (fd == -1) { if (fd == -1) {
GUAC_RDP_DEBUG(1, "open() failed: %s", strerror(errno)); GUAC_RDP_DEBUG(1, "open() failed: %s", strerror(errno));
return guac_rdpdr_fs_get_errorcode(errno); return guac_rdp_fs_get_errorcode(errno);
} }
/* Get file ID, init file */ /* Get file ID, init file */
file_id = guac_pool_next_int(data->file_id_pool); file_id = guac_pool_next_int(fs->file_id_pool);
file = &(data->files[file_id]); file = &(fs->files[file_id]);
file->fd = fd; file->fd = fd;
file->dir = NULL; file->dir = NULL;
file->dir_pattern[0] = '\0'; file->dir_pattern[0] = '\0';
@ -307,10 +311,6 @@ int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path,
/* If information cannot be retrieved, fake it */ /* If information cannot be retrieved, fake it */
else { else {
guac_client_log_info(device->rdpdr->client,
"Unable to read information for \"%s\"",
real_path);
/* Init information to 0, lacking any alternative */ /* Init information to 0, lacking any alternative */
file->size = 0; file->size = 0;
file->ctime = 0; file->ctime = 0;
@ -320,21 +320,21 @@ int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path,
} }
data->open_files++; fs->open_files++;
return file_id; return file_id;
} }
int guac_rdpdr_fs_read(guac_rdpdr_device* device, int file_id, int offset, int guac_rdp_fs_read(guac_rdp_fs* fs, int file_id, int offset,
void* buffer, int length) { void* buffer, int length) {
int bytes_read; int bytes_read;
guac_rdpdr_fs_file* file = guac_rdpdr_fs_get_file(device, file_id); guac_rdp_fs_file* file = guac_rdp_fs_get_file(fs, file_id);
if (file == NULL) { if (file == NULL) {
GUAC_RDP_DEBUG(1, "Read from bad file_id: %i", file_id); GUAC_RDP_DEBUG(1, "Read from bad file_id: %i", file_id);
return GUAC_RDPDR_FS_EINVAL; return GUAC_RDP_FS_EINVAL;
} }
/* Attempt read */ /* Attempt read */
@ -343,21 +343,21 @@ int guac_rdpdr_fs_read(guac_rdpdr_device* device, int file_id, int offset,
/* Translate errno on error */ /* Translate errno on error */
if (bytes_read < 0) if (bytes_read < 0)
return guac_rdpdr_fs_get_errorcode(errno); return guac_rdp_fs_get_errorcode(errno);
return bytes_read; return bytes_read;
} }
int guac_rdpdr_fs_write(guac_rdpdr_device* device, int file_id, int offset, int guac_rdp_fs_write(guac_rdp_fs* fs, int file_id, int offset,
void* buffer, int length) { void* buffer, int length) {
int bytes_written; int bytes_written;
guac_rdpdr_fs_file* file = guac_rdpdr_fs_get_file(device, file_id); guac_rdp_fs_file* file = guac_rdp_fs_get_file(fs, file_id);
if (file == NULL) { if (file == NULL) {
GUAC_RDP_DEBUG(1, "Write to bad file_id: %i", file_id); GUAC_RDP_DEBUG(1, "Write to bad file_id: %i", file_id);
return GUAC_RDPDR_FS_EINVAL; return GUAC_RDP_FS_EINVAL;
} }
/* Attempt write */ /* Attempt write */
@ -366,32 +366,32 @@ int guac_rdpdr_fs_write(guac_rdpdr_device* device, int file_id, int offset,
/* Translate errno on error */ /* Translate errno on error */
if (bytes_written < 0) if (bytes_written < 0)
return guac_rdpdr_fs_get_errorcode(errno); return guac_rdp_fs_get_errorcode(errno);
return bytes_written; return bytes_written;
} }
int guac_rdpdr_fs_rename(guac_rdpdr_device* device, int file_id, int guac_rdp_fs_rename(guac_rdp_fs* fs, int file_id,
const char* new_path) { const char* new_path) {
char real_path[GUAC_RDPDR_FS_MAX_PATH]; char real_path[GUAC_RDP_FS_MAX_PATH];
char normalized_path[GUAC_RDPDR_FS_MAX_PATH]; char normalized_path[GUAC_RDP_FS_MAX_PATH];
guac_rdpdr_fs_file* file = guac_rdpdr_fs_get_file(device, file_id); guac_rdp_fs_file* file = guac_rdp_fs_get_file(fs, file_id);
if (file == NULL) { if (file == NULL) {
GUAC_RDP_DEBUG(1, "Rename of bad file_id: %i", file_id); GUAC_RDP_DEBUG(1, "Rename of bad file_id: %i", file_id);
return GUAC_RDPDR_FS_EINVAL; return GUAC_RDP_FS_EINVAL;
} }
/* Normalize path, return no-such-file if invalid */ /* Normalize path, return no-such-file if invalid */
if (guac_rdpdr_fs_normalize_path(new_path, normalized_path)) { if (guac_rdp_fs_normalize_path(new_path, normalized_path)) {
GUAC_RDP_DEBUG(1, "Normalization of path \"%s\" failed.", new_path); GUAC_RDP_DEBUG(1, "Normalization of path \"%s\" failed.", new_path);
return GUAC_RDPDR_FS_ENOENT; return GUAC_RDP_FS_ENOENT;
} }
/* Translate normalized path to real path */ /* Translate normalized path to real path */
__guac_rdpdr_fs_translate_path(device, normalized_path, real_path); __guac_rdp_fs_translate_path(fs, normalized_path, real_path);
GUAC_RDP_DEBUG(2, "Renaming \"%s\" -> \"%s\"", file->real_path, real_path); GUAC_RDP_DEBUG(2, "Renaming \"%s\" -> \"%s\"", file->real_path, real_path);
@ -399,25 +399,23 @@ int guac_rdpdr_fs_rename(guac_rdpdr_device* device, int file_id,
if (rename(file->real_path, real_path)) { if (rename(file->real_path, real_path)) {
GUAC_RDP_DEBUG(1, "rename() failed: \"%s\" -> \"%s\"", GUAC_RDP_DEBUG(1, "rename() failed: \"%s\" -> \"%s\"",
file->real_path, real_path); file->real_path, real_path);
return guac_rdpdr_fs_get_errorcode(errno); return guac_rdp_fs_get_errorcode(errno);
} }
return 0; return 0;
} }
void guac_rdpdr_fs_close(guac_rdpdr_device* device, int file_id) { void guac_rdp_fs_close(guac_rdp_fs* fs, int file_id) {
guac_rdpdr_fs_data* data = (guac_rdpdr_fs_data*) device->data; guac_rdp_fs_file* file = guac_rdp_fs_get_file(fs, file_id);
guac_rdpdr_fs_file* file = guac_rdpdr_fs_get_file(device, file_id);
if (file == NULL) { if (file == NULL) {
GUAC_RDP_DEBUG(2, "Ignoring close for bad file_id: %i", GUAC_RDP_DEBUG(2, "Ignoring close for bad file_id: %i",
file_id); file_id);
return; return;
} }
file = &(data->files[file_id]); file = &(fs->files[file_id]);
GUAC_RDP_DEBUG(2, "Closed \"%s\" (file_id=%i)", GUAC_RDP_DEBUG(2, "Closed \"%s\" (file_id=%i)",
file->absolute_path, file_id); file->absolute_path, file_id);
@ -434,23 +432,22 @@ void guac_rdpdr_fs_close(guac_rdpdr_device* device, int file_id) {
free(file->real_path); free(file->real_path);
/* Free ID back to pool */ /* Free ID back to pool */
guac_pool_free_int(data->file_id_pool, file_id); guac_pool_free_int(fs->file_id_pool, file_id);
data->open_files--; fs->open_files--;
} }
const char* guac_rdpdr_fs_read_dir(guac_rdpdr_device* device, int file_id) { const char* guac_rdp_fs_read_dir(guac_rdp_fs* fs, int file_id) {
guac_rdpdr_fs_data* data = (guac_rdpdr_fs_data*) device->data; guac_rdp_fs_file* file;
guac_rdpdr_fs_file* file;
struct dirent* result; struct dirent* result;
/* Only read if file ID is valid */ /* Only read if file ID is valid */
if (file_id < 0 || file_id >= GUAC_RDPDR_FS_MAX_FILES) if (file_id < 0 || file_id >= GUAC_RDP_FS_MAX_FILES)
return NULL; return NULL;
file = &(data->files[file_id]); file = &(fs->files[file_id]);
/* Open directory if not yet open, stop if error */ /* Open directory if not yet open, stop if error */
if (file->dir == NULL) { if (file->dir == NULL) {
@ -472,11 +469,11 @@ const char* guac_rdpdr_fs_read_dir(guac_rdpdr_device* device, int file_id) {
} }
int guac_rdpdr_fs_normalize_path(const char* path, char* abs_path) { int guac_rdp_fs_normalize_path(const char* path, char* abs_path) {
int i; int i;
int path_depth = 0; int path_depth = 0;
char path_component_data[GUAC_RDPDR_FS_MAX_PATH]; char path_component_data[GUAC_RDP_FS_MAX_PATH];
const char* path_components[64]; const char* path_components[64];
const char** current_path_component = &(path_components[0]); const char** current_path_component = &(path_components[0]);
@ -490,10 +487,10 @@ int guac_rdpdr_fs_normalize_path(const char* path, char* abs_path) {
path++; path++;
/* Copy path into component data for parsing */ /* Copy path into component data for parsing */
strncpy(path_component_data, path, GUAC_RDPDR_FS_MAX_PATH-1); strncpy(path_component_data, path, GUAC_RDP_FS_MAX_PATH-1);
/* Find path components within path */ /* Find path components within path */
for (i=0; i<GUAC_RDPDR_FS_MAX_PATH; i++) { for (i=0; i<GUAC_RDP_FS_MAX_PATH; i++) {
/* If current character is a path separator, parse as component */ /* If current character is a path separator, parse as component */
char c = path_component_data[i]; char c = path_component_data[i];
@ -553,14 +550,14 @@ int guac_rdpdr_fs_normalize_path(const char* path, char* abs_path) {
} }
int guac_rdpdr_fs_convert_path(const char* parent, const char* rel_path, char* abs_path) { int guac_rdp_fs_convert_path(const char* parent, const char* rel_path, char* abs_path) {
int i; int i;
char combined_path[GUAC_RDPDR_FS_MAX_PATH]; char combined_path[GUAC_RDP_FS_MAX_PATH];
char* current = combined_path; char* current = combined_path;
/* Copy parent path */ /* Copy parent path */
for (i=0; i<GUAC_RDPDR_FS_MAX_PATH; i++) { for (i=0; i<GUAC_RDP_FS_MAX_PATH; i++) {
char c = *(parent++); char c = *(parent++);
if (c == 0) if (c == 0)
@ -574,27 +571,25 @@ int guac_rdpdr_fs_convert_path(const char* parent, const char* rel_path, char* a
*(current++) = '\\'; *(current++) = '\\';
/* Copy remaining path */ /* Copy remaining path */
strncpy(current, rel_path, GUAC_RDPDR_FS_MAX_PATH-i-2); strncpy(current, rel_path, GUAC_RDP_FS_MAX_PATH-i-2);
/* Normalize into provided buffer */ /* Normalize into provided buffer */
return guac_rdpdr_fs_normalize_path(combined_path, abs_path); return guac_rdp_fs_normalize_path(combined_path, abs_path);
} }
guac_rdpdr_fs_file* guac_rdpdr_fs_get_file(guac_rdpdr_device* device, guac_rdp_fs_file* guac_rdp_fs_get_file(guac_rdp_fs* fs, int file_id) {
int file_id) {
/* Validate ID */ /* Validate ID */
guac_rdpdr_fs_data* data = (guac_rdpdr_fs_data*) device->data; if (file_id < 0 || file_id >= GUAC_RDP_FS_MAX_FILES)
if (file_id < 0 || file_id >= GUAC_RDPDR_FS_MAX_FILES)
return NULL; return NULL;
/* Return file at given ID */ /* Return file at given ID */
return &(data->files[file_id]); return &(fs->files[file_id]);
} }
int guac_rdpdr_fs_matches(const char* filename, const char* pattern) { int guac_rdp_fs_matches(const char* filename, const char* pattern) {
return fnmatch(pattern, filename, FNM_NOESCAPE) != 0; return fnmatch(pattern, filename, FNM_NOESCAPE) != 0;
} }

View File

@ -35,101 +35,89 @@
* *
* ***** END LICENSE BLOCK ***** */ * ***** END LICENSE BLOCK ***** */
#ifndef __GUAC_RDPDR_FS_H #ifndef __GUAC_RDP_FS_H
#define __GUAC_RDPDR_FS_H #define __GUAC_RDP_FS_H
/** /**
* Functions and macros specific to filesystem handling and initialization * Functions and macros specific to filesystem handling and initialization
* independent of RDP. The functions here may deal with the RDPDR device * independent of RDP. The functions here may deal with the filesystem device
* directly, but their semantics must not deal with RDP protocol messaging. * directly, but their semantics must not deal with RDP protocol messaging.
* Functions here represent a virtual Windows-style filesystem on top of UNIX * Functions here represent a virtual Windows-style filesystem on top of UNIX
* system calls and structures, using the guac_rdpdr_device structure as a home * system calls and structures, using the guac_rdp_fs structure as a home
* for common data. * for common data.
* *
* @file rdpdr_fs.h * @file rdp_fs.h
*/ */
#ifdef ENABLE_WINPR
#include <winpr/stream.h>
#else
#include "compat/winpr-stream.h"
#endif
#include <sys/types.h> #include <sys/types.h>
#include <stdint.h>
#include <dirent.h> #include <dirent.h>
#include <guacamole/pool.h> #include <guacamole/pool.h>
#include "rdpdr_service.h"
/**
* The index of the blob to use when sending files.
*/
#define GUAC_RDPDR_FS_BLOB 1
/** /**
* The maximum number of file IDs to provide. * The maximum number of file IDs to provide.
*/ */
#define GUAC_RDPDR_FS_MAX_FILES 128 #define GUAC_RDP_FS_MAX_FILES 128
/** /**
* The maximum number of bytes in a path string. * The maximum number of bytes in a path string.
*/ */
#define GUAC_RDPDR_FS_MAX_PATH 4096 #define GUAC_RDP_FS_MAX_PATH 4096
/** /**
* Error code returned when no more file IDs can be allocated. * Error code returned when no more file IDs can be allocated.
*/ */
#define GUAC_RDPDR_FS_ENFILE -1 #define GUAC_RDP_FS_ENFILE -1
/** /**
* Error code returned when no such file exists. * Error code returned when no such file exists.
*/ */
#define GUAC_RDPDR_FS_ENOENT -2 #define GUAC_RDP_FS_ENOENT -2
/** /**
* Error code returned when the operation required a directory * Error code returned when the operation required a directory
* but the file was not a directory. * but the file was not a directory.
*/ */
#define GUAC_RDPDR_FS_ENOTDIR -3 #define GUAC_RDP_FS_ENOTDIR -3
/** /**
* Error code returned when insufficient space exists to complete * Error code returned when insufficient space exists to complete
* the operation. * the operation.
*/ */
#define GUAC_RDPDR_FS_ENOSPC -4 #define GUAC_RDP_FS_ENOSPC -4
/** /**
* Error code returned when the operation requires a normal file but * Error code returned when the operation requires a normal file but
* a directory was given. * a directory was given.
*/ */
#define GUAC_RDPDR_FS_EISDIR -5 #define GUAC_RDP_FS_EISDIR -5
/** /**
* Error code returned when permission is denied. * Error code returned when permission is denied.
*/ */
#define GUAC_RDPDR_FS_EACCES -6 #define GUAC_RDP_FS_EACCES -6
/** /**
* Error code returned when the operation cannot be completed because the * Error code returned when the operation cannot be completed because the
* file already exists. * file already exists.
*/ */
#define GUAC_RDPDR_FS_EEXIST -7 #define GUAC_RDP_FS_EEXIST -7
/** /**
* Error code returned when invalid parameters were given. * Error code returned when invalid parameters were given.
*/ */
#define GUAC_RDPDR_FS_EINVAL -8 #define GUAC_RDP_FS_EINVAL -8
/** /**
* Error code returned when the operation is not implemented. * Error code returned when the operation is not implemented.
*/ */
#define GUAC_RDPDR_FS_ENOSYS -9 #define GUAC_RDP_FS_ENOSYS -9
/** /**
* Error code returned when the operation is not supported. * Error code returned when the operation is not supported.
*/ */
#define GUAC_RDPDR_FS_ENOTSUP -10 #define GUAC_RDP_FS_ENOTSUP -10
/* /*
* Access constants. * Access constants.
@ -201,7 +189,7 @@
/** /**
* An arbitrary file on the virtual filesystem of the Guacamole drive. * An arbitrary file on the virtual filesystem of the Guacamole drive.
*/ */
typedef struct guac_rdpdr_fs_file { typedef struct guac_rdp_fs_file {
/** /**
* The absolute path, including filename, of this file. * The absolute path, including filename, of this file.
@ -233,7 +221,7 @@ typedef struct guac_rdpdr_fs_file {
/** /**
* The pattern the check directory contents against, if any. * The pattern the check directory contents against, if any.
*/ */
char dir_pattern[GUAC_RDPDR_FS_MAX_PATH]; char dir_pattern[GUAC_RDP_FS_MAX_PATH];
/** /**
* Bitwise OR of all associated Windows file attributes. * Bitwise OR of all associated Windows file attributes.
@ -260,12 +248,17 @@ typedef struct guac_rdpdr_fs_file {
*/ */
uint64_t atime; uint64_t atime;
} guac_rdpdr_fs_file; } guac_rdp_fs_file;
/** /**
* Data specific to an instance of the printer device. * A virtual filesystem implementing RDP-style operations.
*/ */
typedef struct guac_rdpdr_fs_data { typedef struct guac_rdp_fs {
/**
* The root of the filesystem.
*/
char* drive_path;
/** /**
* The number of currently open files. * The number of currently open files.
@ -280,37 +273,41 @@ typedef struct guac_rdpdr_fs_data {
/** /**
* All available file structures. * All available file structures.
*/ */
guac_rdpdr_fs_file files[GUAC_RDPDR_FS_MAX_FILES]; guac_rdp_fs_file files[GUAC_RDP_FS_MAX_FILES];
} guac_rdpdr_fs_data; } guac_rdp_fs;
/** /**
* Registers a new filesystem device within the RDPDR plugin. This must be done * Allocates a new filesystem given a root path.
* before RDPDR connection finishes.
*/ */
void guac_rdpdr_register_fs(guac_rdpdrPlugin* rdpdr); guac_rdp_fs* guac_rdp_fs_alloc(const char* drive_path);
/**
* Frees the given filesystem.
*/
void guac_rdp_fs_free(guac_rdp_fs* fs);
/** /**
* Converts the given relative path to an absolute path based on the given * Converts the given relative path to an absolute path based on the given
* parent path. If the path cannot be converted, non-zero is returned. * parent path. If the path cannot be converted, non-zero is returned.
*/ */
int guac_rdpdr_fs_convert_path(const char* parent, const char* rel_path, char* abs_path); int guac_rdp_fs_convert_path(const char* parent, const char* rel_path, char* abs_path);
/** /**
* Translates the given errno error code to a GUAC_RDPDR_FS error code. * Translates the given errno error code to a GUAC_RDP_FS error code.
*/ */
int guac_rdpdr_fs_get_errorcode(int err); int guac_rdp_fs_get_errorcode(int err);
/** /**
* Teanslates the given GUAC_RDPDR_FS error code to an RDPDR status code. * Teanslates the given GUAC_RDP_FS error code to an RDPDR status code.
*/ */
int guac_rdpdr_fs_get_status(int err); int guac_rdp_fs_get_status(int err);
/** /**
* Returns the next available file ID, or an error code less than zero * Returns the next available file ID, or an error code less than zero
* if an error occurs. * if an error occurs.
*/ */
int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path, int guac_rdp_fs_open(guac_rdp_fs* fs, const char* path,
int access, int file_attributes, int create_disposition, int access, int file_attributes, int create_disposition,
int create_options); int create_options);
@ -319,7 +316,7 @@ int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path,
* file having the given ID. Returns the number of bytes read, zero on EOF, * file having the given ID. Returns the number of bytes read, zero on EOF,
* and an error code if an error occurs. * and an error code if an error occurs.
*/ */
int guac_rdpdr_fs_read(guac_rdpdr_device* device, int file_id, int offset, int guac_rdp_fs_read(guac_rdp_fs* fs, int file_id, int offset,
void* buffer, int length); void* buffer, int length);
/** /**
@ -327,48 +324,47 @@ int guac_rdpdr_fs_read(guac_rdpdr_device* device, int file_id, int offset,
* file having the given ID. Returns the number of bytes written, and an * file having the given ID. Returns the number of bytes written, and an
* error code if an error occurs. * error code if an error occurs.
*/ */
int guac_rdpdr_fs_write(guac_rdpdr_device* device, int file_id, int offset, int guac_rdp_fs_write(guac_rdp_fs* fs, int file_id, int offset,
void* buffer, int length); void* buffer, int length);
/** /**
* Renames (moves) the file with the given ID to the new path specified. * 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. * Returns zero on success, or an error code if an error occurs.
*/ */
int guac_rdpdr_fs_rename(guac_rdpdr_device* device, int file_id, int guac_rdp_fs_rename(guac_rdp_fs* fs, int file_id,
const char* new_path); const char* new_path);
/** /**
* Frees the given file ID, allowing future open operations to reuse it. * Frees the given file ID, allowing future open operations to reuse it.
*/ */
void guac_rdpdr_fs_close(guac_rdpdr_device* device, int file_id); void guac_rdp_fs_close(guac_rdp_fs* fs, int file_id);
/** /**
* Given an arbitrary path, which may contain ".." and ".", creates an * Given an arbitrary path, which may contain ".." and ".", creates an
* absolute path which does NOT contain ".." or ".". * absolute path which does NOT contain ".." or ".".
*/ */
int guac_rdpdr_fs_normalize_path(const char* path, char* abs_path); int guac_rdp_fs_normalize_path(const char* path, char* abs_path);
/** /**
* Given a parent path and a relative path, produces a normalized absolute path. * Given a parent path and a relative path, produces a normalized absolute path.
*/ */
int guac_rdpdr_fs_convert_path(const char* parent, const char* rel_path, char* abs_path); int guac_rdp_fs_convert_path(const char* parent, const char* rel_path, char* abs_path);
/** /**
* Returns the next filename within the directory having the given file ID, * Returns the next filename within the directory having the given file ID,
* or NULL if no more files. * or NULL if no more files.
*/ */
const char* guac_rdpdr_fs_read_dir(guac_rdpdr_device* device, int file_id); const char* guac_rdp_fs_read_dir(guac_rdp_fs* fs, int file_id);
/** /**
* Returns the file having the given ID, or NULL if no such file exists. * Returns the file having the given ID, or NULL if no such file exists.
*/ */
guac_rdpdr_fs_file* guac_rdpdr_fs_get_file(guac_rdpdr_device* device, guac_rdp_fs_file* guac_rdp_fs_get_file(guac_rdp_fs* fs, int file_id);
int file_id);
/** /**
* Returns whether the given filename matches the given pattern. * Returns whether the given filename matches the given pattern.
*/ */
int guac_rdpdr_fs_matches(const char* filename, const char* pattern); int guac_rdp_fs_matches(const char* filename, const char* pattern);
#endif #endif

View File

@ -0,0 +1,69 @@
/* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is libguac-client-rdp.
*
* The Initial Developer of the Original Code is
* Michael Jumper.
* Portions created by the Initial Developer are Copyright (C) 2011
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
#ifndef __GUAC_RDP_STATUS_H
#define __GUAC_RDP_STATUS_H
/**
* RDP-specific status constants.
*
* @file rdp_status.h
*/
#define STATUS_SUCCESS 0x00000000
#define STATUS_NO_MORE_FILES 0x80000006
#define STATUS_DEVICE_OFF_LINE 0x80000010
#define STATUS_NOT_IMPLEMENTED 0xC0000002
#define STATUS_INVALID_PARAMETER 0xC000000D
#define STATUS_NO_SUCH_FILE 0xC000000F
#define STATUS_END_OF_FILE 0xC0000011
#define STATUS_ACCESS_DENIED 0xC0000022
#define STATUS_OBJECT_NAME_COLLISION 0xC0000035
#define STATUS_DISK_FULL 0xC000007F
#define STATUS_FILE_INVALID 0xC0000098
#define STATUS_FILE_IS_A_DIRECTORY 0xC00000BA
#define STATUS_NOT_SUPPORTED 0xC00000BB
#define STATUS_NOT_A_DIRECTORY 0xC0000103
#define STATUS_TOO_MANY_OPENED_FILES 0xC000011F
#define STATUS_CANNOT_DELETE 0xC0000121
#define STATUS_FILE_DELETED 0xC0000123
#define STATUS_FILE_CLOSED 0xC0000128
#define STATUS_FILE_SYSTEM_LIMITATION 0xC0000427
#define STATUS_FILE_TOO_LARGE 0xC0000904
#endif