diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs.c b/src/protocols/rdp/guac_rdpdr/rdpdr_fs.c index 8104c385..5357c693 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs.c @@ -41,6 +41,7 @@ #include #include #include +#include #ifdef ENABLE_WINPR #include @@ -111,6 +112,44 @@ static void __guac_rdpdr_fs_translate_path(guac_rdpdr_device* device, } +int guac_rdpdr_fs_get_errorcode(int err) { + + /* Translate errno codes to GUAC_RDPDR_FS codes */ + if (err == ENFILE) return GUAC_RDPDR_FS_ENFILE; + if (err == ENOENT) return GUAC_RDPDR_FS_ENOENT; + if (err == ENOTDIR) return GUAC_RDPDR_FS_ENOTDIR; + if (err == ENOSPC) return GUAC_RDPDR_FS_ENOSPC; + if (err == EISDIR) return GUAC_RDPDR_FS_EISDIR; + if (err == EACCES) return GUAC_RDPDR_FS_EACCES; + if (err == EEXIST) return GUAC_RDPDR_FS_EEXIST; + if (err == EINVAL) return GUAC_RDPDR_FS_EINVAL; + if (err == ENOSYS) return GUAC_RDPDR_FS_ENOSYS; + if (err == ENOTSUP) return GUAC_RDPDR_FS_ENOTSUP; + + /* Default to invalid parameter */ + return GUAC_RDPDR_FS_EINVAL; + +} + +int guac_rdpdr_fs_get_status(int err) { + + /* Translate GUAC_RDPDR_FS error code to RDPDR status code */ + if (err == GUAC_RDPDR_FS_ENFILE) return STATUS_NO_MORE_FILES; + if (err == GUAC_RDPDR_FS_ENOENT) return STATUS_NO_SUCH_FILE; + if (err == GUAC_RDPDR_FS_ENOTDIR) return STATUS_NOT_A_DIRECTORY; + if (err == GUAC_RDPDR_FS_ENOSPC) return STATUS_DISK_FULL; + if (err == GUAC_RDPDR_FS_EISDIR) return STATUS_FILE_IS_A_DIRECTORY; + if (err == GUAC_RDPDR_FS_EACCES) return STATUS_ACCESS_DENIED; + if (err == GUAC_RDPDR_FS_EEXIST) return STATUS_OBJECT_NAME_COLLISION; + if (err == GUAC_RDPDR_FS_EINVAL) return STATUS_INVALID_PARAMETER; + if (err == GUAC_RDPDR_FS_ENOSYS) return STATUS_NOT_IMPLEMENTED; + if (err == GUAC_RDPDR_FS_ENOTSUP) return STATUS_NOT_SUPPORTED; + + /* Default to invalid parameter */ + return STATUS_INVALID_PARAMETER; + +} + int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path, int access, int file_attributes, int create_disposition, int create_options) { @@ -195,7 +234,7 @@ int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path, /* Unrecognised disposition */ default: - return GUAC_RDPDR_FS_ENOENT; /* FIXME: Replace with real return value */ + return GUAC_RDPDR_FS_ENOSYS; } @@ -206,7 +245,7 @@ int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path, /* Open file */ fd = open(real_path, flags, S_IRUSR | S_IWUSR); if (fd == -1) - return GUAC_RDPDR_FS_ENOENT; + return guac_rdpdr_fs_get_errorcode(errno); /* Get file ID, init file */ file_id = guac_pool_next_int(data->file_id_pool); diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_fs.h b/src/protocols/rdp/guac_rdpdr/rdpdr_fs.h index 561afe52..ecba92f3 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs.h +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs.h @@ -83,10 +83,54 @@ #define GUAC_RDPDR_FS_ENFILE -1 /** - * Error code returned with no such file exists. + * Error code returned when no such file exists. */ #define GUAC_RDPDR_FS_ENOENT -2 +/** + * Error code returned when the operation required a directory + * but the file was not a directory. + */ +#define GUAC_RDPDR_FS_ENOTDIR -3 + +/** + * Error code returned when insufficient space exists to complete + * the operation. + */ +#define GUAC_RDPDR_FS_ENOSPC -4 + +/** + * Error code returned when the operation requires a normal file but + * a directory was given. + */ +#define GUAC_RDPDR_FS_EISDIR -5 + +/** + * Error code returned when permission is denied. + */ +#define GUAC_RDPDR_FS_EACCES -6 + +/** + * Error code returned when the operation cannot be completed because the + * file already exists. + */ +#define GUAC_RDPDR_FS_EEXIST -7 + +/** + * Error code returned when invalid parameters were given. + */ +#define GUAC_RDPDR_FS_EINVAL -8 + +/** + * Error code returned when the operation is not implemented. + */ +#define GUAC_RDPDR_FS_ENOSYS -9 + +/** + * Error code returned when the operation is not supported. + */ +#define GUAC_RDPDR_FS_ENOTSUP -10 + /* * Access constants. */ @@ -240,6 +284,16 @@ void guac_rdpdr_register_fs(guac_rdpdrPlugin* rdpdr); */ int guac_rdpdr_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. + */ +int guac_rdpdr_fs_get_errorcode(int err); + +/** + * Teanslates the given GUAC_RDPDR_FS error code to an RDPDR status code. + */ +int guac_rdpdr_fs_get_status(int err); + /** * Returns the next available file ID, or an error code less than zero * 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 9dc53931..8c717aa4 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_fs_messages.c @@ -86,24 +86,13 @@ void guac_rdpdr_fs_process_create(guac_rdpdr_device* device, file_id = guac_rdpdr_fs_open(device, path, desired_access, file_attributes, create_disposition, create_options); - /* If no file IDs available, notify server */ - if (file_id == GUAC_RDPDR_FS_ENFILE) { + /* If an error occurred, notify server */ + if (file_id < 0) { guac_client_log_error(device->rdpdr->client, - "File open refused - too many open files"); + "File open refused (%i): \"%s\"", file_id, path); output_stream = guac_rdpdr_new_io_completion(device, completion_id, - STATUS_TOO_MANY_OPENED_FILES, 5); - Stream_Write_UINT32(output_stream, 0); /* fileId */ - Stream_Write_UINT8(output_stream, 0); /* information */ - } - - /* If file does not exist, notify server */ - else if (file_id == GUAC_RDPDR_FS_ENOENT) { - guac_client_log_error(device->rdpdr->client, - "File open refused - does not exist: \"%s\"", path); - - output_stream = guac_rdpdr_new_io_completion(device, completion_id, - STATUS_NO_SUCH_FILE, 5); + guac_rdpdr_fs_get_status(file_id), 5); Stream_Write_UINT32(output_stream, 0); /* fileId */ Stream_Write_UINT8(output_stream, 0); /* information */ } diff --git a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h index 54d664ad..113306b0 100644 --- a/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h +++ b/src/protocols/rdp/guac_rdpdr/rdpdr_messages.h @@ -204,12 +204,17 @@ #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