From f02164036949f266ea4aadd294f3a4742ea17193 Mon Sep 17 00:00:00 2001 From: Laxmikant Rashinkar Date: Sat, 30 Mar 2013 15:51:50 -0700 Subject: [PATCH] folder redirection: we can now detect devices plugged in after a session has started --- sesman/chansrv/chansrv_fuse.c | 121 +++++++++++++++------------------- sesman/chansrv/devredir.c | 24 ++++++- sesman/chansrv/devredir.h | 3 +- sesman/startwm.sh | 3 +- 4 files changed, 80 insertions(+), 71 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, diff --git a/sesman/startwm.sh b/sesman/startwm.sh index 02fc7956..2dfaacec 100755 --- a/sesman/startwm.sh +++ b/sesman/startwm.sh @@ -3,7 +3,8 @@ # change the order in line below to run to run whatever window manager you # want, default to kde -SESSIONS="gnome-session blackbox fluxbox startxfce4 startkde xterm" +#SESSIONS="gnome-session blackbox fluxbox startxfce4 startkde xterm" +SESSIONS="mate-session blackbox fluxbox startxfce4 startkde xterm" #start the window manager wm_start()