Actually resolve and open files.
This commit is contained in:
parent
f24d4b58fa
commit
9fcb3e3678
@ -35,6 +35,10 @@
|
|||||||
*
|
*
|
||||||
* ***** END LICENSE BLOCK ***** */
|
* ***** END LICENSE BLOCK ***** */
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
|
||||||
#ifdef ENABLE_WINPR
|
#ifdef ENABLE_WINPR
|
||||||
#include <winpr/stream.h>
|
#include <winpr/stream.h>
|
||||||
#else
|
#else
|
||||||
@ -51,27 +55,148 @@
|
|||||||
|
|
||||||
#include <freerdp/utils/svc_plugin.h>
|
#include <freerdp/utils/svc_plugin.h>
|
||||||
|
|
||||||
int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path) {
|
/**
|
||||||
|
* Translates an absolute Windows path to an absolute path which is within the "drive path"
|
||||||
|
* specified in the connection settings.
|
||||||
|
*/
|
||||||
|
static char* __guac_rdpdr_fs_translate_path(guac_rdpdr_device* device,
|
||||||
|
const char* path, char* path_buffer) {
|
||||||
|
|
||||||
|
/* Get drive path */
|
||||||
|
rdp_guac_client_data* client_data = (rdp_guac_client_data*) device->rdpdr->client->data;
|
||||||
|
char* drive_path = client_data->settings.drive_path;
|
||||||
|
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* Start with path from settings */
|
||||||
|
for (i=0; i<GUAC_RDPDR_FS_MAX_PATH-1; i++) {
|
||||||
|
|
||||||
|
/* Copy character, break on end-of-string */
|
||||||
|
if ((*(path_buffer++) = *(drive_path++)) == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Translate path */
|
||||||
|
for (; i<GUAC_RDPDR_FS_MAX_PATH-1; i++) {
|
||||||
|
|
||||||
|
/* Stop at end of string */
|
||||||
|
char c = *path;
|
||||||
|
if (c == 0)
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Disallow ".." */
|
||||||
|
if (c == '.' && *(path-1) == '.')
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
/* Translate backslashes to forward slashes */
|
||||||
|
if (c == '\\')
|
||||||
|
c = '/';
|
||||||
|
|
||||||
|
/* Store in real path buffer */
|
||||||
|
path_buffer[i] = c;
|
||||||
|
|
||||||
|
/* Next path character */
|
||||||
|
path++;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Null terminator */
|
||||||
|
path_buffer[i] = 0;
|
||||||
|
return path_buffer;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path,
|
||||||
|
int access, int create_disposition) {
|
||||||
|
|
||||||
guac_rdpdr_fs_data* data = (guac_rdpdr_fs_data*) device->data;
|
guac_rdpdr_fs_data* data = (guac_rdpdr_fs_data*) device->data;
|
||||||
|
char path_buffer[GUAC_RDPDR_FS_MAX_PATH];
|
||||||
|
|
||||||
|
int fd;
|
||||||
int file_id;
|
int file_id;
|
||||||
guac_rdpdr_fs_file* file;
|
guac_rdpdr_fs_file* file;
|
||||||
|
|
||||||
|
mode_t mode;
|
||||||
|
int flags = 0;
|
||||||
|
|
||||||
/* 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 (data->open_files >= GUAC_RDPDR_FS_MAX_FILES)
|
||||||
return GUAC_RDPDR_FS_ENFILE;
|
return GUAC_RDPDR_FS_ENFILE;
|
||||||
|
|
||||||
/* If path is empty, the file does not exist */
|
/* If path is empty or relative, the file does not exist */
|
||||||
if (path[0] == '\0')
|
if (path[0] != '\\')
|
||||||
return GUAC_RDPDR_FS_ENOENT;
|
return GUAC_RDPDR_FS_ENOENT;
|
||||||
|
|
||||||
file->type = GUAC_RDPDR_FS_FILE;
|
/* Translate access into mode */
|
||||||
/* STUB */
|
if (access & ACCESS_FILE_READ_DATA) {
|
||||||
|
if (access & (ACCESS_FILE_WRITE_DATA | ACCESS_FILE_APPEND_DATA))
|
||||||
|
mode = O_RDWR;
|
||||||
|
else
|
||||||
|
mode = O_RDONLY;
|
||||||
|
}
|
||||||
|
else if (access & (ACCESS_FILE_WRITE_DATA | ACCESS_FILE_APPEND_DATA))
|
||||||
|
mode = O_WRONLY;
|
||||||
|
else
|
||||||
|
return GUAC_RDPDR_FS_ENOENT; /* FIXME: Replace with real return value */
|
||||||
|
|
||||||
/* Get file ID */
|
/* If append access requested, add appropriate option */
|
||||||
|
if (access & ACCESS_FILE_APPEND_DATA)
|
||||||
|
flags |= O_APPEND;
|
||||||
|
|
||||||
|
switch (create_disposition) {
|
||||||
|
|
||||||
|
/* Supersede (replace) if exists, otherwise create */
|
||||||
|
case DISP_FILE_SUPERSEDE:
|
||||||
|
flags |= O_TRUNC | O_CREAT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Open file if exists and do not overwrite, fail otherwise */
|
||||||
|
case DISP_FILE_OPEN:
|
||||||
|
flags |= O_APPEND;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Create if not exist, fail otherwise */
|
||||||
|
case DISP_FILE_CREATE:
|
||||||
|
flags |= O_EXCL;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Open if exists, create otherwise */
|
||||||
|
case DISP_FILE_OPEN_IF:
|
||||||
|
flags |= O_APPEND | O_CREAT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Overwrite if exists, fail otherwise */
|
||||||
|
case DISP_FILE_OVERWRITE:
|
||||||
|
/* No flag necessary - default functionality of open */
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Overwrite if exists, create otherwise */
|
||||||
|
case DISP_FILE_OVERWRITE_IF:
|
||||||
|
flags |= O_CREAT;
|
||||||
|
break;
|
||||||
|
|
||||||
|
/* Unrecognised disposition */
|
||||||
|
default:
|
||||||
|
return GUAC_RDPDR_FS_ENOENT; /* FIXME: Replace with real return value */
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/* If path invalid, return no such file */
|
||||||
|
if (__guac_rdpdr_fs_translate_path(device, path, path_buffer) == NULL)
|
||||||
|
return GUAC_RDPDR_FS_ENOENT;
|
||||||
|
|
||||||
|
guac_client_log_info(device->rdpdr->client, "Path translated to \"%s\"", path_buffer);
|
||||||
|
|
||||||
|
/* Open file */
|
||||||
|
fd = open(path_buffer, flags, mode);
|
||||||
|
if (fd == -1)
|
||||||
|
return GUAC_RDPDR_FS_ENOENT;
|
||||||
|
|
||||||
|
/* Get file ID, init file */
|
||||||
file_id = guac_pool_next_int(data->file_id_pool);
|
file_id = guac_pool_next_int(data->file_id_pool);
|
||||||
file = &(data->files[file_id]);
|
file = &(data->files[file_id]);
|
||||||
|
file->fd = fd;
|
||||||
|
|
||||||
data->open_files++;
|
data->open_files++;
|
||||||
|
|
||||||
|
@ -60,6 +60,11 @@
|
|||||||
*/
|
*/
|
||||||
#define GUAC_RDPDR_FS_MAX_FILES 128
|
#define GUAC_RDPDR_FS_MAX_FILES 128
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The maximum number of bytes in a path string.
|
||||||
|
*/
|
||||||
|
#define GUAC_RDPDR_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.
|
||||||
*/
|
*/
|
||||||
@ -70,6 +75,25 @@
|
|||||||
*/
|
*/
|
||||||
#define GUAC_RDPDR_FS_ENOENT -2
|
#define GUAC_RDPDR_FS_ENOENT -2
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Access constants.
|
||||||
|
*/
|
||||||
|
#define ACCESS_FILE_READ_DATA 0x00000001
|
||||||
|
#define ACCESS_FILE_WRITE_DATA 0x00000002
|
||||||
|
#define ACCESS_FILE_APPEND_DATA 0x00000004
|
||||||
|
#define ACCESS_DELETE 0x00010000
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Create disposition constants.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define DISP_FILE_SUPERSEDE 0x00000000
|
||||||
|
#define DISP_FILE_OPEN 0x00000001
|
||||||
|
#define DISP_FILE_CREATE 0x00000002
|
||||||
|
#define DISP_FILE_OPEN_IF 0x00000003
|
||||||
|
#define DISP_FILE_OVERWRITE 0x00000004
|
||||||
|
#define DISP_FILE_OVERWRITE_IF 0x00000005
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Information constants.
|
* Information constants.
|
||||||
*/
|
*/
|
||||||
@ -102,36 +126,11 @@
|
|||||||
*/
|
*/
|
||||||
#define WINDOWS_TIME(t) ((t - ((uint64_t) 11644473600)) * 10000000)
|
#define WINDOWS_TIME(t) ((t - ((uint64_t) 11644473600)) * 10000000)
|
||||||
|
|
||||||
/**
|
|
||||||
* Enumeration of all supported file types.
|
|
||||||
*/
|
|
||||||
typedef enum guac_rdpdr_fs_file_type {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A regular file - either a file or directory.
|
|
||||||
*/
|
|
||||||
GUAC_RDPDR_FS_FILE,
|
|
||||||
|
|
||||||
/**
|
|
||||||
* A disk device - here, this is always virtual, and always the containing
|
|
||||||
* volume (the Guacamole drive).
|
|
||||||
*/
|
|
||||||
GUAC_RDPDR_FS_VOLUME,
|
|
||||||
|
|
||||||
} guac_rdpdr_fs_file_type;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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_rdpdr_fs_file {
|
||||||
|
|
||||||
/**
|
|
||||||
* The type of this file - either a FILE (file or directory) or a
|
|
||||||
* VOLUME (virtual file, represents the virtual device represented by
|
|
||||||
* the Guacamole drive).
|
|
||||||
*/
|
|
||||||
guac_rdpdr_fs_file_type type;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Associated local file descriptor.
|
* Associated local file descriptor.
|
||||||
*/
|
*/
|
||||||
@ -170,7 +169,8 @@ void guac_rdpdr_register_fs(guac_rdpdrPlugin* rdpdr);
|
|||||||
/**
|
/**
|
||||||
* Returns the next available file ID, or -1 if none available.
|
* Returns the next available file ID, or -1 if none available.
|
||||||
*/
|
*/
|
||||||
int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path);
|
int guac_rdpdr_fs_open(guac_rdpdr_device* device, const char* path,
|
||||||
|
int access, int create_disposition);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Frees the given file ID, allowing future open operations to reuse it.
|
* Frees the given file ID, allowing future open operations to reuse it.
|
||||||
|
@ -78,7 +78,7 @@ void guac_rdpdr_fs_process_create(guac_rdpdr_device* device,
|
|||||||
guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), path, path_length/2 - 1);
|
guac_rdp_utf16_to_utf8(Stream_Pointer(input_stream), path, path_length/2 - 1);
|
||||||
|
|
||||||
/* Open file */
|
/* Open file */
|
||||||
file_id = guac_rdpdr_fs_open(device, path);
|
file_id = guac_rdpdr_fs_open(device, path, desired_access, create_disposition);
|
||||||
|
|
||||||
/* Write header */
|
/* Write header */
|
||||||
Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE);
|
Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE);
|
||||||
|
Loading…
Reference in New Issue
Block a user