Actually resolve and open files.

This commit is contained in:
Michael Jumper 2013-07-29 17:57:24 -07:00
parent f24d4b58fa
commit 9fcb3e3678
3 changed files with 158 additions and 33 deletions

View File

@ -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++;

View File

@ -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.

View File

@ -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);