Actually resolve and open files.
This commit is contained in:
parent
f24d4b58fa
commit
9fcb3e3678
@ -35,6 +35,10 @@
|
||||
*
|
||||
* ***** END LICENSE BLOCK ***** */
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
#ifdef ENABLE_WINPR
|
||||
#include <winpr/stream.h>
|
||||
#else
|
||||
@ -51,27 +55,148 @@
|
||||
|
||||
#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;
|
||||
char path_buffer[GUAC_RDPDR_FS_MAX_PATH];
|
||||
|
||||
int fd;
|
||||
int file_id;
|
||||
guac_rdpdr_fs_file* file;
|
||||
|
||||
mode_t mode;
|
||||
int flags = 0;
|
||||
|
||||
/* If no files available, return too many open */
|
||||
if (data->open_files >= GUAC_RDPDR_FS_MAX_FILES)
|
||||
return GUAC_RDPDR_FS_ENFILE;
|
||||
|
||||
/* If path is empty, the file does not exist */
|
||||
if (path[0] == '\0')
|
||||
/* If path is empty or relative, the file does not exist */
|
||||
if (path[0] != '\\')
|
||||
return GUAC_RDPDR_FS_ENOENT;
|
||||
|
||||
file->type = GUAC_RDPDR_FS_FILE;
|
||||
/* STUB */
|
||||
/* Translate access into mode */
|
||||
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 = &(data->files[file_id]);
|
||||
file->fd = fd;
|
||||
|
||||
data->open_files++;
|
||||
|
||||
|
@ -60,6 +60,11 @@
|
||||
*/
|
||||
#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.
|
||||
*/
|
||||
@ -70,6 +75,25 @@
|
||||
*/
|
||||
#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.
|
||||
*/
|
||||
@ -102,36 +126,11 @@
|
||||
*/
|
||||
#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.
|
||||
*/
|
||||
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.
|
||||
*/
|
||||
@ -170,7 +169,8 @@ void guac_rdpdr_register_fs(guac_rdpdrPlugin* rdpdr);
|
||||
/**
|
||||
* 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.
|
||||
|
@ -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);
|
||||
|
||||
/* Open file */
|
||||
file_id = guac_rdpdr_fs_open(device, path);
|
||||
file_id = guac_rdpdr_fs_open(device, path, desired_access, create_disposition);
|
||||
|
||||
/* Write header */
|
||||
Stream_Write_UINT16(output_stream, RDPDR_CTYP_CORE);
|
||||
|
Loading…
Reference in New Issue
Block a user