Merge branch 'master' of github.com:FreeRDP/xrdp

ulab-next
Jay Sorg 12 years ago
commit be44e0be4b

@ -18,24 +18,20 @@
/* /*
* TODO * TODO
* o need to support sym links
* o when creating dir/file, ensure it does not already exist * o when creating dir/file, ensure it does not already exist
* o enable changing metadata for files/folders (time, owner, mode etc)
* o do not allow dirs to be created in ino==1 except for .clipbard and share mounts * o do not allow dirs to be created in ino==1 except for .clipbard and share mounts
* o xrdp_fs needs to grow dynamically - currently it is fixed at 1k or 4k
* o fix the HACK where I have to use my own buf instead of g_buffer * o fix the HACK where I have to use my own buf instead of g_buffer
* this is in func xfuse_check_wait_objs() * this is in func xfuse_check_wait_objs()
* o if fuse mount point is already mounted, I get segfault * o if fuse mount point is already mounted, I get segfault
* o in open, check for modes such as O_TRUNC, O_APPEND * o in open, check for modes such as O_TRUNC, O_APPEND
* o copying over an existing file does not work * o copying over an existing file does not work
* o need to keep track of open files, reqd during rename
* o need to use dir notification for changed files and update xrdp fs
* o copying over an existing file does not work
* o after a dir is created, the device cannot be unmounted on the client side * o after a dir is created, the device cannot be unmounted on the client side
* so something is holding it up * so something is holding it up
* o in thunar, when I move a file by dragging to another folder, the file
* is getting copied instead of being moved
* o unable to edit files in vi
* o fuse ops to support * o fuse ops to support
* o touch does not work * o touch does not work
* o keep track of lookup_count
* o chmod must work * o chmod must work
* o cat >> file is not working * o cat >> file is not working
* *
@ -45,6 +41,7 @@
/* FUSE mount point */ /* FUSE mount point */
char g_fuse_root_path[256] = ""; char g_fuse_root_path[256] = "";
char g_fuse_clipboard_path[256] = ""; /* for clipboard use */
#ifndef XRDP_FUSE #ifndef XRDP_FUSE
@ -104,6 +101,7 @@ void xfuse_devredir_cb_file_close(void *vp) {}
#include "arch.h" #include "arch.h"
#include "os_calls.h" #include "os_calls.h"
#include "chansrv_fuse.h" #include "chansrv_fuse.h"
#include "list.h"
#define min(x, y) ((x) < (y) ? (x) : (y)) #define min(x, y) ((x) < (y) ? (x) : (y))
@ -201,8 +199,17 @@ struct xfuse_handle
}; };
typedef struct xfuse_handle XFUSE_HANDLE; typedef struct xfuse_handle XFUSE_HANDLE;
/* globals */ /* used for file data request sent to client */
struct req_list_item
{
fuse_req_t req;
int stream_id;
int lindex;
int off;
int size;
};
static struct list *g_req_list = 0;
static struct xrdp_fs g_xrdp_fs; /* an inst of xrdp file system */ static struct xrdp_fs g_xrdp_fs; /* an inst of xrdp file system */
static char *g_mount_point = 0; /* our FUSE mount point */ static char *g_mount_point = 0; /* our FUSE mount point */
static struct fuse_lowlevel_ops g_xfuse_ops; /* setup FUSE callbacks */ static struct fuse_lowlevel_ops g_xfuse_ops; /* setup FUSE callbacks */
@ -257,6 +264,8 @@ int dev_redir_file_read(void *fusep, tui32 device_id, tui32 FileId,
int dev_redir_file_write(void *fusep, tui32 device_id, tui32 FileId, int dev_redir_file_write(void *fusep, tui32 device_id, tui32 FileId,
const char *buf, tui32 Length, tui64 Offset); const char *buf, tui32 Length, tui64 Offset);
int devredir_file_close(void *fusep, tui32 device_id, tui32 FileId);
/* forward declarations for FUSE callbacks */ /* forward declarations for FUSE callbacks */
static void xfuse_cb_lookup(fuse_req_t req, fuse_ino_t parent, static void xfuse_cb_lookup(fuse_req_t req, fuse_ino_t parent,
const char *name); const char *name);
@ -311,36 +320,9 @@ static void xfuse_cb_create(fuse_req_t req, fuse_ino_t parent,
const char *name, mode_t mode, const char *name, mode_t mode,
struct fuse_file_info *fi); struct fuse_file_info *fi);
// LK_TODO may not need to be implemented /* clipboard calls */
#if 0 int clipboard_request_file_data(int stream_id, int lindex, int offset,
static void xfuse_cb_statfs(fuse_req_t req, fuse_ino_t ino); int request_bytes);
static void xfuse_cb_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
const char *value, size_t size, int flags);
static void xfuse_cb_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
size_t size);
static void xfuse_cb_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size);
static void xfuse_cb_access(fuse_req_t req, fuse_ino_t ino, int mask);
static void xfuse_cb_getlk(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi, struct flock *lock);
static void xfuse_cb_setlk(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi, struct flock *lock,
int sleep);
static void xfuse_cb_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
struct fuse_file_info *fi, unsigned flags,
const void *in_buf, size_t in_bufsz,
size_t out_bufsz);
static void xfuse_cb_poll(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi,
struct fuse_pollhandle *ph);
#endif
static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
int to_set, struct fuse_file_info *fi); int to_set, struct fuse_file_info *fi);
@ -360,7 +342,6 @@ static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
int xfuse_init() int xfuse_init()
{ {
struct fuse_args args = FUSE_ARGS_INIT(0, NULL); struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
char opt[1024];
/* if already inited, just return */ /* if already inited, just return */
if (g_xfuse_inited) if (g_xfuse_inited)
@ -377,6 +358,7 @@ int xfuse_init()
/* define FUSE mount point to ~/xrdp_client */ /* define FUSE mount point to ~/xrdp_client */
g_snprintf(g_fuse_root_path, 255, "%s/xrdp_client", g_getenv("HOME")); g_snprintf(g_fuse_root_path, 255, "%s/xrdp_client", g_getenv("HOME"));
g_snprintf(g_fuse_clipboard_path, 255, "%s/.clipboard", g_fuse_root_path);
/* if FUSE mount point does not exist, create it */ /* if FUSE mount point does not exist, create it */
if (!g_directory_exist(g_fuse_root_path)) if (!g_directory_exist(g_fuse_root_path))
@ -409,28 +391,8 @@ int xfuse_init()
g_xfuse_ops.getattr = xfuse_cb_getattr; g_xfuse_ops.getattr = xfuse_cb_getattr;
g_xfuse_ops.setattr = xfuse_cb_setattr; g_xfuse_ops.setattr = xfuse_cb_setattr;
#if 0
g_xfuse_ops.statfs = xfuse_cb_statfs;
g_xfuse_ops.listxattr = xfuse_cb_listxattr;
g_xfuse_ops.getlk = xfuse_cb_getlk;
g_xfuse_ops.setlk = xfuse_cb_setlk;
g_xfuse_ops.ioctl = xfuse_cb_ioctl;
g_xfuse_ops.poll = xfuse_cb_poll;
g_xfuse_ops.access = xfuse_cb_access;
g_xfuse_ops.setxattr = xfuse_cb_setxattr;
g_xfuse_ops.getxattr = xfuse_cb_getxattr;
#endif
fuse_opt_add_arg(&args, "xrdp-chansrv"); fuse_opt_add_arg(&args, "xrdp-chansrv");
fuse_opt_add_arg(&args, g_fuse_root_path); fuse_opt_add_arg(&args, g_fuse_root_path);
#if 0
sprintf(opt, "-o uid=%d,gid=%d", g_getuid(), g_getgid());
fuse_opt_add_arg(&args, opt);
#else
/* disable multi threading */
sprintf(opt, "-s");
fuse_opt_add_arg(&args, opt);
#endif
if (xfuse_init_lib(&args)) if (xfuse_init_lib(&args))
{ {
@ -471,6 +433,12 @@ int xfuse_deinit()
g_buffer = 0; g_buffer = 0;
} }
if (g_req_list != 0)
{
list_delete(g_req_list);
g_req_list = 0;
}
g_xfuse_inited = 0; g_xfuse_inited = 0;
return 0; return 0;
} }
@ -553,11 +521,11 @@ int xfuse_get_wait_objs(tbus *objs, int *count, int *timeout)
int xfuse_create_share(tui32 device_id, char *dirname) int xfuse_create_share(tui32 device_id, char *dirname)
{ {
/* LK_TODO need to specify parent dir, mode */ #if 0
XFUSE_INFO *fip; XFUSE_INFO *fip;
#endif
XRDP_INODE *xinode; XRDP_INODE *xinode;
tui32 saved_inode; /* tui32 saved_inode; */
if (dirname == NULL || strlen(dirname) == 0) if (dirname == NULL || strlen(dirname) == 0)
return -1; return -1;
@ -583,7 +551,7 @@ int xfuse_create_share(tui32 device_id, char *dirname)
xinode->device_id = device_id; xinode->device_id = device_id;
g_xrdp_fs.num_entries++; g_xrdp_fs.num_entries++;
saved_inode = xinode->inode; /* saved_inode = xinode->inode; */
/* insert it in xrdp fs */ /* insert it in xrdp fs */
g_xrdp_fs.inode_table[xinode->inode] = xinode; g_xrdp_fs.inode_table[xinode->inode] = xinode;
@ -605,7 +573,7 @@ int xfuse_create_share(tui32 device_id, char *dirname)
/* enumerate root dir, do not call FUSE when done */ /* enumerate root dir, do not call FUSE when done */
fip->req = NULL; fip->req = NULL;
fip->inode = 1; // LK_TODO saved_inode; fip->inode = 1; /* TODO saved_inode; */
strncpy(fip->name, dirname, 1024); strncpy(fip->name, dirname, 1024);
fip->name[1023] = 0; fip->name[1023] = 0;
fip->device_id = device_id; fip->device_id = device_id;
@ -617,36 +585,107 @@ int xfuse_create_share(tui32 device_id, char *dirname)
} }
/** /**
* Clear all clipboard entries in xrdp_fs
* *
* This function is called by clipboard code
* *
* @return 0 on success, -1 on failure * @return 0 on success, -1 on failure
*****************************************************************************/ *****************************************************************************/
int xfuse_clear_clip_dir(void) int xfuse_clear_clip_dir(void)
{ {
return 0; // CLIPBOARD_TODO int i;
XRDP_INODE *xinode;
XRDP_INODE *xip;
log_debug("entered");
/* xinode for .clipboard */
xip = g_xrdp_fs.inode_table[2];
for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++)
{
if ((xinode = g_xrdp_fs.inode_table[i]) == NULL)
continue;
if (xinode->parent_inode == 2)
{
g_xrdp_fs.inode_table[i] = NULL;
free(xinode);
xip->nentries--;
}
}
return 0;
} }
/** /**
* * Return clipboard data to fuse
* *
* @return 0 on success, -1 on failure * @return 0 on success, -1 on failure
*****************************************************************************/ *****************************************************************************/
int xfuse_file_contents_range(int stream_id, char *data, int data_bytes) int xfuse_file_contents_range(int stream_id, char *data, int data_bytes)
{ {
return 0; // CLIPBOARD_TODO log_debug("entered: stream_id=%d data_bytes=%d", stream_id, data_bytes);
struct req_list_item *rli;
if ((rli = (struct req_list_item *) list_get_item(g_req_list, 0)) == NULL)
{
log_error("range error!");
return -1;
}
log_debug("lindex=%d off=%d size=%d", rli->lindex, rli->off, rli->size);
fuse_reply_buf(rli->req, data, data_bytes);
list_remove_item(g_req_list, 0);
if (g_req_list->count <= 0)
{
log_debug("completed all requests");
return 0;
}
/* send next request */
rli = (struct req_list_item *) list_get_item(g_req_list, 0);
if (rli == NULL)
{
log_error("range error!");
return -1;
}
log_debug("requesting clipboard file data");
clipboard_request_file_data(rli->stream_id, rli->lindex,
rli->off, rli->size);
return 0;
} }
/** /**
* Create a file in .clipboard dir
* *
* This function is called by clipboard code
* *
* @return 0 on success, -1 on failure * @return 0 on success, -1 on failure
*****************************************************************************/ *****************************************************************************/
int xfuse_add_clip_dir_item(char *filename, int flags, int size, int lindex) int xfuse_add_clip_dir_item(char *filename, int flags, int size, int lindex)
{ {
return 0; // CLIPBOARD_TODO log_debug("entered: filename=%s flags=%d size=%d lindex=%d",
filename, flags, size, lindex);
/* add entry to xrdp_fs */
XRDP_INODE *xinode = xfuse_create_file_in_xrdp_fs(0, /* device id */
2, /* parent inode */
filename,
S_IFREG);
xinode->size = size;
xinode->lindex = lindex;
return 0;
} }
/** /**
@ -657,7 +696,8 @@ int xfuse_add_clip_dir_item(char *filename, int flags, int size, int lindex)
int xfuse_file_contents_size(int stream_id, int file_size) int xfuse_file_contents_size(int stream_id, int file_size)
{ {
return 0; // CLIPBOARD_TODO log_debug("entered: stream_id=%d file_size=%d", stream_id, file_size);
return 0;
} }
/***************************************************************************** /*****************************************************************************
@ -705,6 +745,9 @@ static int xfuse_init_lib(struct fuse_args *args)
g_buffer = calloc(g_bufsize, 1); g_buffer = calloc(g_bufsize, 1);
g_fd = fuse_chan_fd(g_ch); g_fd = fuse_chan_fd(g_ch);
g_req_list = list_create();
g_req_list->auto_free = 1;
return 0; return 0;
} }
@ -789,7 +832,7 @@ static int xfuse_init_xrdp_fs()
g_xrdp_fs.inode_table[2] = xino; g_xrdp_fs.inode_table[2] = xino;
xino->parent_inode = 1; xino->parent_inode = 1;
xino->inode = 2; xino->inode = 2;
xino->nentries = 1; xino->nentries = 0;
xino->mode = S_IFDIR | 0755; xino->mode = S_IFDIR | 0755;
xino->uid = getuid(); xino->uid = getuid();
xino->gid = getgid(); xino->gid = getgid();
@ -1076,8 +1119,6 @@ static struct xrdp_inode * xfuse_create_file_in_xrdp_fs(tui32 device_id,
return NULL; return NULL;
} }
log_debug("S_IFDIR=0x%x S_IFREG=0x%x type=0x%x", S_IFDIR, S_IFREG, type);
xinode->parent_inode = pinode; xinode->parent_inode = pinode;
xinode->inode = g_xrdp_fs.next_node++; xinode->inode = g_xrdp_fs.next_node++;
xinode->nlink = 1; xinode->nlink = 1;
@ -1458,7 +1499,7 @@ void xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode)
/* insert it in xrdp fs and update lookup count */ /* insert it in xrdp fs and update lookup count */
g_xrdp_fs.inode_table[xinode->inode] = xinode; g_xrdp_fs.inode_table[xinode->inode] = xinode;
g_xrdp_fs.inode_table[fip->inode]->nentries; g_xrdp_fs.inode_table[fip->inode]->nentries++; /* this was missing */
xfuse_update_xrdpfs_size(); xfuse_update_xrdpfs_size();
} }
@ -1759,7 +1800,6 @@ done:
void xfuse_devredir_cb_read_file(void *vp, char *buf, size_t length) void xfuse_devredir_cb_read_file(void *vp, char *buf, size_t length)
{ {
XFUSE_HANDLE *fh;
XFUSE_INFO *fip; XFUSE_INFO *fip;
fip = (XFUSE_INFO *) vp; fip = (XFUSE_INFO *) vp;
@ -1773,7 +1813,6 @@ void xfuse_devredir_cb_read_file(void *vp, char *buf, size_t length)
void xfuse_devredir_cb_write_file(void *vp, char *buf, size_t length) void xfuse_devredir_cb_write_file(void *vp, char *buf, size_t length)
{ {
XRDP_INODE *xinode; XRDP_INODE *xinode;
XFUSE_HANDLE *fh;
XFUSE_INFO *fip; XFUSE_INFO *fip;
fip = (XFUSE_INFO *) vp; fip = (XFUSE_INFO *) vp;
@ -1962,131 +2001,6 @@ static void xfuse_cb_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
return; return;
} }
static void xfuse_cb_lookup_TODO(fuse_req_t req, fuse_ino_t parent, const char *name)
{
XFUSE_INFO *fip;
XRDP_INODE *xinode;
struct fuse_entry_param e;
tui32 device_id;
char full_path[4096];
char *cptr;
/* SPEEDUP_TODO */
printf("###### cb_lookup: looking for parent=%d name=%s\n", (int) parent, name);
log_debug("ENTERED: looking for parent=%d name=%s", (int) parent, name);
xfuse_dump_fs();
if (!xfuse_is_inode_valid(parent))
{
log_error("inode %d is not valid", parent);
fuse_reply_err(req, EBADF);
return;
}
if ((xinode = xfuse_get_inode_from_pinode_name(parent, name)) != NULL)
{
log_debug("got match: device_id=%d", xinode->device_id);
/* got a full match; if this dir is located on a remote device */
/* and is not synced, do a remote look up */
#ifdef USE_SYNC_FLAG
if ((xinode->device_id != 0) && (!xinode->is_synced))
goto do_remote_lookup;
#else
if (xinode->device_id != 0)
goto do_remote_lookup;
#endif
memset(&e, 0, sizeof(e));
e.ino = xinode->inode;
e.attr_timeout = XFUSE_ATTR_TIMEOUT;
e.entry_timeout = XFUSE_ENTRY_TIMEOUT;
e.attr.st_ino = xinode->inode;
e.attr.st_mode = xinode->mode;
e.attr.st_nlink = xinode->nlink;
e.attr.st_uid = xinode->uid;
e.attr.st_gid = xinode->gid;
e.attr.st_size = xinode->size;
e.attr.st_atime = xinode->atime;
e.attr.st_mtime = xinode->mtime;
e.attr.st_ctime = xinode->ctime;
e.generation = 1;
fuse_reply_entry(req, &e);
log_debug("found entry in xrdp fs; returning");
return;
}
else
{
log_debug("xinode is NULL for parent=%d name=%s", (int) parent, name);
}
do_remote_lookup:
/* if ino belongs to a redirected share, pass the call to devredir; */
/* when done, devredir will invoke xfuse_devredir_cb_enum_dir_done(...) */
strcpy(full_path, name);
log_debug("full_path=%s name=%s", full_path, name);
device_id = xfuse_get_device_id_for_inode((tui32) parent, full_path);
log_debug("device_id=%d", device_id);
if (device_id != 0)
{
log_debug("did not find entry; redirecting call to dev_redir");
printf("????????? xfuse_cb_lookup() doing remote lookup for %s\n", name);
if ((fip = calloc(1, sizeof(XFUSE_INFO))) == NULL)
{
log_error("system out of memory");
fuse_reply_err(req, ENOMEM);
return;
}
fip->req = req;
fip->inode = parent;
strncpy(fip->name, name, 1024);
fip->name[1023] = 0;
fip->invoke_fuse = 1;
fip->device_id = device_id;
if (parent != 1)
{
strcat(full_path, "/");
strcat(full_path, name);
}
/* we want path minus 'root node of the share' */
if ((cptr = strchr(full_path, '/')) == NULL)
{
/* enumerate root dir */
if (dev_redir_get_dir_listing((void *) fip, device_id, "\\"))
{
log_error("failed to send dev_redir_get_dir_listing() cmd");
fuse_reply_buf(req, NULL, 0);
}
else
{
log_debug("dev_redir_get_dir_listing() called");
}
}
else
{
if (dev_redir_get_dir_listing((void *) fip, device_id, cptr))
{
log_error("failed to send dev_redir_get_dir_listing() cmd");
fuse_reply_buf(req, NULL, 0);
}
}
log_debug("cmd sent; reting");
return;
}
log_debug("parent=%d name=%s not found", (int) parent, name);
fuse_reply_err(req, ENOENT);
}
/** /**
* Get file attributes * Get file attributes
*****************************************************************************/ *****************************************************************************/
@ -2202,85 +2116,6 @@ static void xfuse_cb_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
/* enumerate resources on a remote device */ /* enumerate resources on a remote device */
// lK_TODO
#if 0
{
struct dirbuf b;
memset(&b, 0, sizeof(struct dirbuf));
xfuse_dirbuf_add(req, &b, ".", 1);
xfuse_dirbuf_add(req, &b, "..", 1);
xfuse_dirbuf_add(req, &b, "f2", 2);
if (off < b.size)
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
else
fuse_reply_buf(req, NULL, 0);
xfuse_dirbuf_add(req, &b, "f3", 3);
if (off < b.size)
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
else
fuse_reply_buf(req, NULL, 0);
xfuse_dirbuf_add(req, &b, "f4", 4);
if (off < b.size)
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
else
fuse_reply_buf(req, NULL, 0);
xfuse_dirbuf_add(req, &b, "f5", 5);
if (off < b.size)
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
else
fuse_reply_buf(req, NULL, 0);
xfuse_dirbuf_add(req, &b, "f6", 6);
if (off < b.size)
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
else
fuse_reply_buf(req, NULL, 0);
xfuse_dirbuf_add(req, &b, "f7", 7);
if (off < b.size)
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
else
fuse_reply_buf(req, NULL, 0);
xfuse_dirbuf_add(req, &b, "f8", 8);
if (off < b.size)
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
else
fuse_reply_buf(req, NULL, 0);
xfuse_dirbuf_add(req, &b, "f9", 9);
if (off < b.size)
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
else
fuse_reply_buf(req, NULL, 0);
xfuse_dirbuf_add(req, &b, "f10", 10);
if (off < b.size)
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
else
fuse_reply_buf(req, NULL, 0);
xfuse_dirbuf_add(req, &b, "f11", 11);
if (off < b.size)
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
else
fuse_reply_buf(req, NULL, 0);
xfuse_dirbuf_add(req, &b, "f12", 12);
if (off < b.size)
fuse_reply_buf(req, b.p + off, min(b.size - off, b.size));
else
fuse_reply_buf(req, NULL, 0);
fuse_reply_buf(req, NULL, 0);
return;
}
#endif
#ifdef USE_SYNC_FLAG #ifdef USE_SYNC_FLAG
if (xinode->is_synced) if (xinode->is_synced)
{ {
@ -2337,66 +2172,6 @@ do_remote_lookup:
} }
} }
static void xfuse_cb_readdir_TODO(fuse_req_t req, fuse_ino_t ino, size_t size,
off_t off, struct fuse_file_info *fi)
{
struct xrdp_inode *xinode;
struct dirbuf b;
int i;
(void) fi;
/* SPEEDUP_TODO */
printf("++++++ cb_readdir: looking for inode=%d\n", (int) ino);
log_debug("looking for dir with inode=%d", ino);
if (!xfuse_is_inode_valid(ino))
{
log_error("inode %d is not valid", ino);
fuse_reply_err(req, EBADF);
return;
}
/* does this dir have any entries? */
xinode = g_xrdp_fs.inode_table[ino];
memset(&b, 0, sizeof(b));
if (ino == 1)
{
xfuse_dirbuf_add(req, &b, ".", 1);
xfuse_dirbuf_add(req, &b, "..", 1);
}
else
{
xfuse_dirbuf_add(req, &b, ".", xinode->inode);
xfuse_dirbuf_add(req, &b, "..", xinode->parent_inode);
}
for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++)
{
if ((xinode = g_xrdp_fs.inode_table[i]) == NULL)
continue;
if (xinode->parent_inode == ino)
xfuse_dirbuf_add(req, &b, xinode->name, xinode->inode);
}
if (off < b.size)
fuse_reply_buf(req, b.p + off, min(b.size - off, size));
else
fuse_reply_buf(req, NULL, 0);
free(b.p);
printf("++++++ cb_readdir: leaving\n");
}
/** /**
* Create a directory * Create a directory
*****************************************************************************/ *****************************************************************************/
@ -2816,56 +2591,53 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
} }
device_id = xfuse_get_device_id_for_inode((tui32) ino, full_path); device_id = xfuse_get_device_id_for_inode((tui32) ino, full_path);
if (device_id) if (device_id == 0)
{ {
/* specified file resides on redirected share */ /* specified file is a local resource */
XFUSE_HANDLE *fh = calloc(1, sizeof(XFUSE_HANDLE));
fi->fh = (uint64_t) ((long) fh);
fuse_reply_open(req, fi);
return;
}
if ((fip = calloc(1, sizeof(XFUSE_INFO))) == NULL) /* specified file resides on redirected share */
{ if ((fip = calloc(1, sizeof(XFUSE_INFO))) == NULL)
log_error("system out of memory"); {
fuse_reply_err(req, ENOMEM); log_error("system out of memory");
return; fuse_reply_err(req, ENOMEM);
} return;
}
fip->req = req; fip->req = req;
fip->inode = ino; fip->inode = ino;
fip->invoke_fuse = 1; fip->invoke_fuse = 1;
fip->device_id = device_id; fip->device_id = device_id;
fip->fi = fi; fip->fi = fi;
strncpy(fip->name, full_path, 1024); strncpy(fip->name, full_path, 1024);
fip->name[1023] = 0; fip->name[1023] = 0;
fip->reply_type = RT_FUSE_REPLY_OPEN; fip->reply_type = RT_FUSE_REPLY_OPEN;
/* LK_TODO need to handle open permissions */ /* LK_TODO need to handle open permissions */
/* we want path minus 'root node of the share' */ /* we want path minus 'root node of the share' */
if ((cptr = strchr(full_path, '/')) == NULL) if ((cptr = strchr(full_path, '/')) == NULL)
{ {
/* get dev_redir to open the remote file */ /* get dev_redir to open the remote file */
if (dev_redir_file_open((void *) fip, device_id, "\\", if (dev_redir_file_open((void *) fip, device_id, "\\",
fi->flags, S_IFREG, NULL)) fi->flags, S_IFREG, NULL))
{ {
log_error("failed to send dev_redir_open_file() cmd"); log_error("failed to send dev_redir_open_file() cmd");
fuse_reply_err(req, EREMOTEIO); fuse_reply_err(req, EREMOTEIO);
} }
}
else
{
if (dev_redir_file_open((void *) fip, device_id, cptr,
fi->flags, S_IFREG, NULL))
{
log_error("failed to send dev_redir_get_dir_listing() cmd");
fuse_reply_err(req, EREMOTEIO);
}
}
} }
else else
{ {
/* specified file is a local resource */ if (dev_redir_file_open((void *) fip, device_id, cptr,
//XFUSE_HANDLE *fh; fi->flags, S_IFREG, NULL))
{
log_debug("LK_TODO: this is still a TODO"); log_error("failed to send dev_redir_get_dir_listing() cmd");
fuse_reply_err(req, EINVAL); fuse_reply_err(req, EREMOTEIO);
}
} }
} }
@ -2885,8 +2657,7 @@ static void xfuse_cb_flush(fuse_req_t req, fuse_ino_t ino, struct
if (handle->DeviceId == 0) if (handle->DeviceId == 0)
{ {
/* specified file is a local resource */ /* specified file is a local resource */
log_debug("LK_TODO: this is still a TODO"); fuse_reply_err(req, 0);
fuse_reply_err(req, EBADF);
return; return;
} }
@ -2918,11 +2689,13 @@ static void xfuse_cb_flush(fuse_req_t req, fuse_ino_t ino, struct
static void xfuse_cb_read(fuse_req_t req, fuse_ino_t ino, size_t size, static void xfuse_cb_read(fuse_req_t req, fuse_ino_t ino, size_t size,
off_t off, struct fuse_file_info *fi) off_t off, struct fuse_file_info *fi)
{ {
XFUSE_HANDLE *fh; XFUSE_HANDLE *fh;
XFUSE_INFO *fusep; XFUSE_INFO *fusep;
long handle; XRDP_INODE *xinode;
struct req_list_item *rli;
long handle;
log_debug("want_bytes %d bytes at off %d", size, off); log_debug("want_bytes %ld bytes at off %ld", size, off);
if (fi->fh == 0) if (fi->fh == 0)
{ {
@ -2936,7 +2709,35 @@ static void xfuse_cb_read(fuse_req_t req, fuse_ino_t ino, size_t size,
if (fh->DeviceId == 0) if (fh->DeviceId == 0)
{ {
/* target file is in .clipboard dir */ /* target file is in .clipboard dir */
log_debug(">>>>>>>>>>>>>>>>> THIS IS STILL A TODO!");
log_debug("target file is in .clipboard dir");
if ((xinode = g_xrdp_fs.inode_table[ino]) == NULL)
{
log_error("ino does not exist in xrdp_fs");
fuse_reply_buf(req, 0, 0);
return;
}
rli = (struct req_list_item *)
g_malloc(sizeof(struct req_list_item), 1);
rli->stream_id = 0;
rli->req = req;
rli->lindex = xinode->lindex;
rli->off = off;
rli->size = size;
list_add_item(g_req_list, (tbus) rli);
if (g_req_list->count == 1)
{
log_debug("requesting clipboard file data lindex = %d off = %d size = %d",
rli->lindex, (int) off, (int) size);
clipboard_request_file_data(rli->stream_id, rli->lindex,
(int) off, (int) size);
}
return; return;
} }
@ -3007,88 +2808,12 @@ static void xfuse_cb_create(fuse_req_t req, fuse_ino_t parent,
xfuse_create_dir_or_file(req, parent, name, mode, fi, S_IFREG); xfuse_create_dir_or_file(req, parent, name, mode, fi, S_IFREG);
} }
// LK_TODO may not need to implement the following funcs
#if 0
static void xfuse_cb_statfs(fuse_req_t req, fuse_ino_t ino)
{
log_debug(">>>>>>>>>>>>>>>> LK_TODO: entered");
fuse_reply_err(req, ENOMEM);
}
static void xfuse_cb_setxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
const char *value, size_t size, int flags)
{
log_debug(">>>>>>>>>>>>>>>> LK_TODO: entered");
fuse_reply_err(req, ENOMEM);
}
static void xfuse_cb_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
size_t size)
{
log_debug(">>>>>>>>>>>>>>>> LK_TODO: entered");
fuse_reply_err(req, ENOMEM);
}
static void xfuse_cb_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
{
log_debug(">>>>>>>>>>>>>>>> LK_TODO: entered");
fuse_reply_err(req, ENOMEM);
}
static void xfuse_cb_access(fuse_req_t req, fuse_ino_t ino, int mask)
{
log_debug(">>>>>>>>>>>>>>>> LK_TODO: entered");
fuse_reply_err(req, ENOMEM);
}
static void xfuse_cb_getlk(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi, struct flock *lock)
{
log_debug(">>>>>>>>>>>>>>>> LK_TODO: entered");
fuse_reply_err(req, ENOMEM);
}
static void xfuse_cb_setlk(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi, struct flock *lock,
int sleep)
{
log_debug(">>>>>>>>>>>>>>>> LK_TODO: entered");
fuse_reply_err(req, ENOMEM);
}
static void xfuse_cb_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
struct fuse_file_info *fi, unsigned flags,
const void *in_buf, size_t in_bufsz,
size_t out_bufsz)
{
log_debug(">>>>>>>>>>>>>>>> LK_TODO: entered");
fuse_reply_err(req, ENOMEM);
}
static void xfuse_cb_poll(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi,
struct fuse_pollhandle *ph)
{
log_debug(">>>>>>>>>>>>>>>> LK_TODO: entered");
fuse_reply_err(req, ENOMEM);
}
#endif
static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
int to_set, struct fuse_file_info *fi) int to_set, struct fuse_file_info *fi)
{ {
XRDP_INODE *xinode; XRDP_INODE *xinode;
log_debug(">>>>>>>>>>>>>>>> LK_TODO: entered to_set=0x%x", to_set); log_debug("entered to_set=0x%x", to_set);
if (!xfuse_is_inode_valid(ino)) if (!xfuse_is_inode_valid(ino))
{ {
@ -3102,20 +2827,20 @@ static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
if (to_set & FUSE_SET_ATTR_MODE) if (to_set & FUSE_SET_ATTR_MODE)
{ {
xinode->mode = attr->st_mode; xinode->mode = attr->st_mode;
log_debug(">>>>>>>>>>>>>>>> LK_TODO: FUSE_SET_ATTR_MODE"); log_debug("FUSE_SET_ATTR_MODE");
} }
if (to_set & FUSE_SET_ATTR_UID) if (to_set & FUSE_SET_ATTR_UID)
{ {
xinode->uid = attr->st_uid; xinode->uid = attr->st_uid;
log_debug(">>>>>>>>>>>>>>>> LK_TODO: FUSE_SET_ATTR_UID"); log_debug("FUSE_SET_ATTR_UID");
} }
if (to_set & FUSE_SET_ATTR_GID) if (to_set & FUSE_SET_ATTR_GID)
{ {
xinode->gid = attr->st_gid; xinode->gid = attr->st_gid;
log_debug(">>>>>>>>>>>>>>>> LK_TODO: FUSE_SET_ATTR_GID"); log_debug("FUSE_SET_ATTR_GID");
} }
if (to_set & FUSE_SET_ATTR_SIZE) if (to_set & FUSE_SET_ATTR_SIZE)
@ -3128,25 +2853,25 @@ static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
if (to_set & FUSE_SET_ATTR_ATIME) if (to_set & FUSE_SET_ATTR_ATIME)
{ {
xinode->atime = attr->st_atime; xinode->atime = attr->st_atime;
log_debug(">>>>>>>>>>>>>>>> LK_TODO: FUSE_SET_ATTR_ATIME"); log_debug("FUSE_SET_ATTR_ATIME");
} }
if (to_set & FUSE_SET_ATTR_MTIME) if (to_set & FUSE_SET_ATTR_MTIME)
{ {
xinode->mtime = attr->st_mtime; xinode->mtime = attr->st_mtime;
log_debug(">>>>>>>>>>>>>>>> LK_TODO: FUSE_SET_ATTR_MTIME"); log_debug("FUSE_SET_ATTR_MTIME");
} }
if (to_set & FUSE_SET_ATTR_ATIME_NOW) if (to_set & FUSE_SET_ATTR_ATIME_NOW)
{ {
xinode->atime = attr->st_atime; xinode->atime = attr->st_atime;
log_debug(">>>>>>>>>>>>>>>> LK_TODO: FUSE_SET_ATTR_ATIME_NOW"); log_debug("FUSE_SET_ATTR_ATIME_NOW");
} }
if (to_set & FUSE_SET_ATTR_MTIME_NOW) if (to_set & FUSE_SET_ATTR_MTIME_NOW)
{ {
xinode->mtime = attr->st_mtime; xinode->mtime = attr->st_mtime;
log_debug(">>>>>>>>>>>>>>>> LK_TODO: FUSE_SET_ATTR_MTIME_NOW"); log_debug("FUSE_SET_ATTR_MTIME_NOW");
} }
fuse_reply_attr(req, attr, 1.0); /* LK_TODO just faking for now */ fuse_reply_attr(req, attr, 1.0); /* LK_TODO just faking for now */

@ -38,6 +38,7 @@ struct xrdp_inode
tui32 device_id; /* for file system redirection */ tui32 device_id; /* for file system redirection */
char is_synced; /* dir struct has been read from */ char is_synced; /* dir struct has been read from */
/* remote device, done just once */ /* remote device, done just once */
int lindex; /* used in clipboard operations */
}; };
typedef struct xrdp_inode XRDP_INODE; // LK_TODO use this instead of using struct xrdp_inode typedef struct xrdp_inode XRDP_INODE; // LK_TODO use this instead of using struct xrdp_inode

@ -53,7 +53,7 @@ extern int g_cliprdr_chan_id; /* in chansrv.c */
extern struct clip_s2c g_clip_s2c; /* in clipboard.c */ extern struct clip_s2c g_clip_s2c; /* in clipboard.c */
extern struct clip_c2s g_clip_c2s; /* in clipboard.c */ extern struct clip_c2s g_clip_c2s; /* in clipboard.c */
extern char g_fuse_root_path[]; /* in chansrv_fuse.c */ extern char g_fuse_clipboard_path[];
struct cb_file_info struct cb_file_info
{ {
@ -454,7 +454,9 @@ clipboard_request_file_data(int stream_id, int lindex, int offset,
int size; int size;
int rv; int rv;
LLOGLN(10, ("clipboard_request_file_data:")); LLOGLN(10, ("clipboard_request_file_data: stream_id=%d lindex=%d off=%d request_bytes=%d",
stream_id, lindex, offset, request_bytes));
if (g_file_request_sent_type != 0) if (g_file_request_sent_type != 0)
{ {
LLOGLN(0, ("clipboard_request_file_data: warning, still waiting " LLOGLN(0, ("clipboard_request_file_data: warning, still waiting "
@ -625,8 +627,8 @@ clipboard_c2s_in_files(struct stream *s, char *file_list)
g_strcpy(ptr, "file://"); g_strcpy(ptr, "file://");
ptr += 7; ptr += 7;
str_len = g_strlen(g_fuse_root_path); str_len = g_strlen(g_fuse_clipboard_path);
g_strcpy(ptr, g_fuse_root_path); g_strcpy(ptr, g_fuse_clipboard_path);
ptr += str_len; ptr += str_len;
*ptr = '/'; *ptr = '/';

@ -1024,7 +1024,6 @@ int devredir_file_close(void *fusep, tui32 device_id, tui32 FileId)
if ((irp = dev_redir_irp_find_by_fileid(FileId)) == NULL) if ((irp = dev_redir_irp_find_by_fileid(FileId)) == NULL)
{ {
log_error("no IRP found with FileId = %d", FileId); log_error("no IRP found with FileId = %d", FileId);
xfuse_devredir_cb_read_file(fusep, NULL, 0);
return -1; return -1;
} }
#endif #endif

@ -0,0 +1,21 @@
# := evaluates the expression just once
# = evaluates the expression each time it is used
CFLAGS := $(shell pkg-config --cflags gtk+-2.0)
CFLAGS += -O2 -Wall
#LDFLAGS = -Wl
LIBS := $(shell pkg-config --libs gtk+-2.0)
LIBS += -ldl -lgthread-2.0
OBJS = gtcp-proxy.o gtcp.o
all: gtcp-proxy
gtcp-proxy: $(OBJS)
gcc -Wall $(CFLAGS) $(LDFLAGS) gtcp-proxy.c gtcp.o -o gtcp-proxy $(LIBS)
gtcp.o: gtcp.c
gcc -c gtcp.c
clean::
-rm gtcp-proxy.o gtcp.o gtcp-proxy

@ -0,0 +1,130 @@
/**
* xrdp: A Remote Desktop Protocol server.
*
* Copyright (C) Laxmikant Rashinkar 2013 LK.Rashinkar@gmail.com
*
* Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include <stdio.h>
#include <stdint.h>
#include <string.h>
/**
* An optimized hexdump function
*
* @param address address to display in address column
* @param buf data to hexdump
* @param len number of bytes to dump
*****************************************************************************/
void hexdump(int address, char *buf, int len)
{
uint32_t addr;
char outbuf[80];
int blocks;
int residual;
int i;
int j;
int buf_index;
int index2; /* data column */
int index3; /* ascii column */
unsigned char c;
char cvt[] = {'0', '1', '2', '3', '4', '5', '6', '7',
'8', '9', 'a', 'b', 'c', 'd', 'e', 'f'};
if ((buf == NULL) || (len <= 0))
return;
addr = (address < 0) ? 0 : address;
blocks = len / 16;
residual = len - blocks * 16;
buf_index = 0;
for (i = 0; i < blocks; i++)
{
index2 = 10;
index3 = 60;
outbuf[9] = ' ';
outbuf[8] = ' ';
outbuf[7] = cvt[(addr >> 0) & 0x0000000f];
outbuf[6] = cvt[(addr >> 4) & 0x0000000f];
outbuf[5] = cvt[(addr >> 8) & 0x0000000f];
outbuf[4] = cvt[(addr >> 12) & 0x0000000f];
outbuf[3] = cvt[(addr >> 16) & 0x0000000f];
outbuf[2] = cvt[(addr >> 20) & 0x0000000f];
outbuf[1] = cvt[(addr >> 24) & 0x0000000f];
outbuf[0] = cvt[(addr >> 28) & 0x0000000f];
addr += 16;
/* insert spaces */
outbuf[8] = ' ';
outbuf[9] = ' ';
outbuf[58] = ' ';
outbuf[59] = ' ';
for (j = 0; j < 16; j++)
{
c = buf[buf_index++];
outbuf[index2++] = cvt[(c >> 4) & 0x0f];
outbuf[index2++] = cvt[(c >> 0) & 0x0f];
outbuf[index2++] = ' ';
if ((c >= 0x20) && (c <= 0x7e))
outbuf[index3++] = c;
else
outbuf[index3++] = '.';
}
outbuf[index3] = 0;
puts(outbuf);
}
if (!residual)
return;
outbuf[7] = cvt[(addr >> 0) & 0x0000000f];
outbuf[6] = cvt[(addr >> 4) & 0x0000000f];
outbuf[5] = cvt[(addr >> 8) & 0x0000000f];
outbuf[4] = cvt[(addr >> 12) & 0x0000000f];
outbuf[3] = cvt[(addr >> 16) & 0x0000000f];
outbuf[2] = cvt[(addr >> 20) & 0x0000000f];
outbuf[1] = cvt[(addr >> 24) & 0x0000000f];
outbuf[0] = cvt[(addr >> 28) & 0x0000000f];
addr += 16;
index2 = 10;
index3 = 60;
memset(&outbuf[8], ' ', 68);
for (j = 0; j < residual; j++)
{
c = buf[buf_index++];
outbuf[index2++] = cvt[(c >> 4) & 0x0f];
outbuf[index2++] = cvt[(c >> 0) & 0x0f];
outbuf[index2++] = ' ';
if ((c >= 0x20) && (c <= 0x7e))
outbuf[index3++] = c;
else
outbuf[index3++] = '.';
}
outbuf[index3] = 0;
puts(outbuf);
}
Loading…
Cancel
Save