summaryrefslogtreecommitdiffstats
path: root/sesman/chansrv
diff options
context:
space:
mode:
authorLaxmikant Rashinkar <LK.Rashinkar@gmail.com>2013-03-30 15:51:50 -0700
committerLaxmikant Rashinkar <LK.Rashinkar@gmail.com>2013-03-30 15:51:50 -0700
commitf02164036949f266ea4aadd294f3a4742ea17193 (patch)
treee017e2021abd1709fc76625886b10ed758cacd43 /sesman/chansrv
parentcab868a3a994bff903c5aac96afda648a370f6f1 (diff)
downloadxrdp-proprietary-f02164036949f266ea4aadd294f3a4742ea17193.tar.gz
xrdp-proprietary-f02164036949f266ea4aadd294f3a4742ea17193.zip
folder redirection: we can now detect devices plugged in after a session has started
Diffstat (limited to 'sesman/chansrv')
-rw-r--r--sesman/chansrv/chansrv_fuse.c121
-rw-r--r--sesman/chansrv/devredir.c24
-rw-r--r--sesman/chansrv/devredir.h3
3 files changed, 78 insertions, 70 deletions
diff --git a/sesman/chansrv/chansrv_fuse.c b/sesman/chansrv/chansrv_fuse.c
index f22ef9fc..79bf8714 100644
--- a/sesman/chansrv/chansrv_fuse.c
+++ b/sesman/chansrv/chansrv_fuse.c
@@ -28,11 +28,12 @@
* o if fuse mount point is already mounted, I get segfault
* o in open, check for modes such as O_TRUNC, O_APPEND
* o copying over an existing file does not work
- * o are we calling close?
* 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
+ * so something is holding it up
* o fuse ops to support
- * o rename (mv)
* o touch does not work
* o keep track of lookup_count
* o chmod must work
@@ -40,6 +41,8 @@
*
*/
+// LK_TODO #define USE_SYNC_FLAG
+
/* FUSE mount point */
char g_fuse_root_path[256] = "";
@@ -651,10 +654,10 @@ static int xfuse_init_lib(struct fuse_args *args)
{
// LK_TODO
{
- int i;
+ int i;
- for (i = 0; i < args->argc; i++)
- log_debug("+++++++++++++ argc=%d argv=%s", i, args->argv[i]);
+ for (i = 0; i < args->argc; i++)
+ log_debug("+++++++++++++ argc=%d argv=%s", i, args->argv[i]);
}
if (fuse_parse_cmdline(args, &g_mount_point, 0, 0) < 0)
@@ -900,9 +903,10 @@ static void xfuse_dump_fs()
if ((xinode = g_xrdp_fs.inode_table[i]) == NULL)
continue;
- log_debug("pinode=%d inode=%d nentries=%d mode=0x%x name=%s",
+ log_debug("pinode=%d inode=%d nentries=%d dev_id=%d is_synced=%d name=%s",
(int) xinode->parent_inode, (int) xinode->inode,
- xinode->nentries, xinode->mode, xinode->name);
+ xinode->nentries, xinode->device_id, xinode->is_synced,
+ xinode->name);
}
log_debug("");
}
@@ -944,13 +948,24 @@ static tui32 xfuse_get_device_id_for_inode(tui32 ino, char *full_path)
tui32 child_inode = ino;
char reverse_path[4096];
- reverse_path[0] = 0;
- full_path[0] = 0;
-
/* ino == 1 is a special case; we already know that it is not */
/* associated with any device redirection */
if (ino == 1)
- return 0;
+ {
+ /* just return the device_id for the file in full_path */
+ log_debug("looking for file with pinode=%d name=%s", ino, full_path);
+ xfuse_dump_fs();
+
+ XRDP_INODE *xinode = xfuse_get_inode_from_pinode_name(ino, full_path);
+ full_path[0] = 0;
+ if (xinode)
+ return xinode->device_id;
+ else
+ return 0;
+ }
+
+ reverse_path[0] = 0;
+ full_path[0] = 0;
while (1)
{
@@ -1187,12 +1202,15 @@ void xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode)
return;
}
+/* LK_TODO */
+#if 0
/* do we have a valid inode? */
if (!xfuse_is_inode_valid(fip->inode))
{
log_error("inode %d is not valid", fip->inode);
return;
}
+#endif
/* if filename is . or .. don't add it */
if ((strcmp(xinode->name, ".") == 0) || (strcmp(xinode->name, "..") == 0))
@@ -1207,6 +1225,12 @@ void xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode)
if (target_inode == 0)
return;
+ if (xfuse_does_file_exist(target_inode->inode, xinode->name))
+ {
+ free(xinode);
+ return;
+ }
+
xinode->parent_inode = target_inode->inode;
xinode->inode = g_xrdp_fs.next_node++;
xinode->uid = getuid();
@@ -1327,8 +1351,6 @@ void xfuse_devredir_cb_open_file(void *vp, tui32 DeviceId, tui32 FileId)
if (fip->fi != NULL)
{
- /* LK_TODO fH NEEDS TO BE RELEASED WHEN THE FILE IS CLOSED */
- /* LK_TODO nopen needs to be decremented when file is closed */
if ((fh = calloc(1, sizeof(XFUSE_HANDLE))) == NULL)
{
log_error("system out of memory");
@@ -1558,7 +1580,8 @@ void xfuse_devredir_cb_file_close(void *vp)
if (xinode->nopen > 0)
xinode->nopen--;
- log_debug("after: inode=%d nopen=%d", xinode->inode, xinode->nopen);
+ if ((xinode->nopen == 0) && fip->fi && fip->fi->fh)
+ free((char *) fip->fi->fh);
fuse_reply_err(fip->req, 0);
}
@@ -1594,53 +1617,19 @@ static void xfuse_cb_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
return;
}
-// LK_TODO
-#if 0
- for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++)
+ if ((xinode = xfuse_get_inode_from_pinode_name(parent, name)) != NULL)
{
- if ((xinode = g_xrdp_fs.inode_table[i]) == NULL)
- continue;
-
- /* match parent inode */
- if (xinode->parent_inode != parent)
- continue;
-
- /* match name */
- if (strcmp(xinode->name, name) != 0)
- continue;
+ log_debug("LK_TODO: 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;
-
- 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
- if ((xinode = xfuse_get_inode_from_pinode_name(parent, name)) != NULL)
- {
- /* got a full match; if this dir is located on a remote device */
- /* and is not synced, do a remote look up */
- if ((xinode->device_id != 0) && (!xinode->is_synced))
+ 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;
@@ -1660,14 +1649,19 @@ static void xfuse_cb_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
log_debug("found entry in xrdp fs; returning");
return;
}
-
-#endif
+ 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("LK_TODO: 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");
@@ -1685,8 +1679,11 @@ do_remote_lookup:
fip->invoke_fuse = 1;
fip->device_id = device_id;
- strcat(full_path, "/");
- strcat(full_path, name);
+ 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)
@@ -2230,9 +2227,6 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
char full_path[4096];
tui32 device_id;
- log_debug("LK_TODO: open_flags=0x%x req=%p fi=%p",
- fi->flags, req, fi);
-
if (!xfuse_is_inode_valid(ino))
{
log_error("inode %d is not valid", ino);
@@ -2254,8 +2248,6 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
{
/* specified file resides on redirected share */
- log_debug("LK_TODO looking for file %s in DeviceId=%d", full_path, device_id);
-
if ((fip = calloc(1, sizeof(XFUSE_INFO))) == NULL)
{
log_error("system out of memory");
@@ -2362,13 +2354,10 @@ static void xfuse_cb_read(fuse_req_t req, fuse_ino_t ino, size_t size,
if (fi->fh == 0)
{
- log_debug("LK_TODO: looks like fi->fh is corrupted");
fuse_reply_err(req, EINVAL);
return;
}
- log_debug("$$$$$$$$$$$$$ LK_TODO: fh=0x%llx", fi->fh);
-
handle = fi->fh;
fh = (XFUSE_HANDLE *) handle;
@@ -2394,7 +2383,6 @@ static void xfuse_cb_read(fuse_req_t req, fuse_ino_t ino, size_t size,
fusep->fi = fi;
dev_redir_file_read(fusep, fh->DeviceId, fh->FileId, size, off);
- log_debug("exiting");
}
static void xfuse_cb_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
@@ -2408,7 +2396,6 @@ static void xfuse_cb_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
if (fi->fh == 0)
{
- log_debug("LK_TODO: looks like fi->fh is corrupted");
fuse_reply_err(req, EINVAL);
return;
}
diff --git a/sesman/chansrv/devredir.c b/sesman/chansrv/devredir.c
index ea994436..37afad26 100644
--- a/sesman/chansrv/devredir.c
+++ b/sesman/chansrv/devredir.c
@@ -675,6 +675,7 @@ void dev_redir_proc_device_iocompletion(struct stream *s)
IoStatus);
free(fuse_data);
}
+ dev_redir_irp_delete(irp);
return;
}
@@ -691,6 +692,8 @@ void dev_redir_proc_device_iocompletion(struct stream *s)
fuse_data = dev_redir_fuse_data_dequeue(irp);
xfuse_devredir_cb_open_file(fuse_data->data_ptr,
DeviceId, irp->FileId);
+ if (irp->type == S_IFDIR)
+ dev_redir_irp_delete(irp);
break;
case CID_READ:
@@ -709,6 +712,8 @@ void dev_redir_proc_device_iocompletion(struct stream *s)
case CID_CLOSE:
log_debug("got CID_CLOSE");
+ log_debug("deleting irp with completion_id=%d comp_type=%d",
+ irp->completion_id, irp->completion_type);
dev_redir_irp_delete(irp);
break;
@@ -947,6 +952,7 @@ int dev_redir_file_open(void *fusep, tui32 device_id, char *path,
{
log_debug("creating dir");
CreateOptions = CO_FILE_DIRECTORY_FILE | CO_FILE_SYNCHRONOUS_IO_NONALERT;
+ irp->type = S_IFDIR;
}
else
{
@@ -980,14 +986,23 @@ int dev_redir_file_open(void *fusep, tui32 device_id, char *path,
return rval;
}
-int devredir_file_close(void *fusep, tui32 device_id, tui32 file_id)
+int devredir_file_close(void *fusep, tui32 device_id, tui32 FileId)
{
IRP *irp;
+#if 0
if ((irp = dev_redir_irp_new()) == NULL)
return -1;
irp->completion_id = g_completion_id++;
+#else
+ if ((irp = dev_redir_irp_find_by_fileid(FileId)) == NULL)
+ {
+ log_error("no IRP found with FileId = %d", FileId);
+ xfuse_devredir_cb_read_file(fusep, NULL, 0);
+ return -1;
+ }
+#endif
irp->completion_type = CID_FILE_CLOSE;
irp->device_id = device_id;
dev_redir_fuse_data_enqueue(irp, fusep);
@@ -995,7 +1010,7 @@ int devredir_file_close(void *fusep, tui32 device_id, tui32 file_id)
return dev_redir_send_drive_close_request(RDPDR_CTYP_CORE,
PAKID_CORE_DEVICE_IOREQUEST,
device_id,
- file_id,
+ FileId,
irp->completion_id,
IRP_MJ_CLOSE,
0, 32);
@@ -1216,6 +1231,8 @@ IRP * dev_redir_irp_new()
IRP *irp;
IRP *irp_last;
+ log_debug("=== entered");
+
/* create new IRP */
if ((irp = calloc(1, sizeof(IRP))) == NULL)
{
@@ -1248,6 +1265,9 @@ int dev_redir_irp_delete(IRP *irp)
{
IRP *lirp = g_irp_head;
+ log_debug("=== entered; completion_id=%d type=%d",
+ irp->completion_id, irp->completion_type);
+
if ((irp == NULL) || (lirp == NULL))
return -1;
diff --git a/sesman/chansrv/devredir.h b/sesman/chansrv/devredir.h
index 8f9975d8..231c2626 100644
--- a/sesman/chansrv/devredir.h
+++ b/sesman/chansrv/devredir.h
@@ -55,6 +55,7 @@ struct irp
tui32 FileId; /* RDP client provided unique number */
char pathname[256]; /* absolute pathname */
char gen_buf[1024]; /* for general use */
+ int type;
tui32 device_id; /* identifies remote device */
FUSE_DATA *fd_head; /* point to first FUSE opaque object */
FUSE_DATA *fd_tail; /* point to last FUSE opaque object */
@@ -351,10 +352,10 @@ enum CREATE_OPTIONS
enum COMPLETION_ID
{
CID_CREATE_DIR_REQ = 1,
+ CID_DIRECTORY_CONTROL,
CID_CREATE_OPEN_REQ,
CID_READ,
CID_WRITE,
- CID_DIRECTORY_CONTROL,
CID_CLOSE,
CID_FILE_CLOSE,
CID_RMDIR_OR_FILE,