diff --git a/sesman/chansrv/chansrv_fuse.c b/sesman/chansrv/chansrv_fuse.c index 661d0bca..f43c91ef 100644 --- a/sesman/chansrv/chansrv_fuse.c +++ b/sesman/chansrv/chansrv_fuse.c @@ -125,6 +125,13 @@ void xfuse_devredir_cb_file_close(void *vp) {} g_writeln (_params); \ } +#define log_always(_params...) \ +{ \ + g_write("[%10.10u]: FUSE %s: %d : ALWAYS: ", \ + g_time3(), __func__, __LINE__); \ + g_writeln (_params); \ +} + #define log_info(_params...) \ { \ if (LOG_INFO <= LOG_LEVEL) \ @@ -249,6 +256,7 @@ static int xfuse_does_file_exist(int parent, char *name); static int xfuse_delete_file(int parent, char *name); static int xfuse_delete_file_with_xinode(XRDP_INODE *xinode); static int xfuse_delete_dir_with_xinode(XRDP_INODE *xinode); +static int xfuse_recursive_delete_dir_with_xinode(XRDP_INODE *xinode); static void xfuse_update_xrdpfs_size(); static void xfuse_enum_dir(fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, struct fuse_file_info *fi); @@ -331,6 +339,10 @@ int clipboard_request_file_data(int stream_id, int lindex, int offset, static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, int to_set, struct fuse_file_info *fi); +/* misc calls */ +static void xfuse_mark_as_stale(int pinode); +static void xfuse_delete_stale_entries(int pinode); + /***************************************************************************** ** ** ** public functions - can be called from any code path ** @@ -1245,6 +1257,52 @@ static int xfuse_delete_dir_with_xinode(XRDP_INODE *xinode) return 0; } +/** + * Recursively delete dir with specified inode + *****************************************************************************/ + +static int xfuse_recursive_delete_dir_with_xinode(XRDP_INODE *xinode) +{ + XRDP_INODE *xip; + int i; + + /* make sure it is not a file */ + if ((xinode == NULL) || (xinode->mode & S_IFREG)) + return -1; + + for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++) + { + if ((xip = g_xrdp_fs.inode_table[i]) == NULL) + continue; + + /* look for child inodes */ + if (xip->parent_inode == xinode->inode) + { + /* got one */ + if (xip->mode & S_IFREG) + { + /* regular file */ + g_xrdp_fs.inode_table[xip->parent_inode]->nentries--; + g_xrdp_fs.inode_table[xip->inode] = NULL; + free(xip); + } + else + { + /* got another dir */ + xfuse_recursive_delete_dir_with_xinode(xip); + } + } + } + + /* our parent will have one less dir */ + g_xrdp_fs.inode_table[xinode->parent_inode]->nentries--; + + g_xrdp_fs.inode_table[xinode->inode] = NULL; + free(xinode); + + return 0; +} + static void xfuse_update_xrdpfs_size() { void *vp; @@ -1365,7 +1423,7 @@ void xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode) log_debug("inode=%d name=%s already exists in xrdp_fs; not adding it", fip->inode, xinode->name); free(xinode); - xinode = xip; + xip->stale = 0; return; } @@ -1407,8 +1465,6 @@ void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus) goto done; } - log_debug("fip->req=%p", fip->req); - if (IoStatus != 0) { /* command failed */ @@ -1425,6 +1481,9 @@ void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus) fuse_reply_err(fip->req, EBADF); goto done; } + + xfuse_delete_stale_entries(fip->inode); + #if 0 memset(&b, 0, sizeof(struct dirbuf)); #else @@ -1556,11 +1615,11 @@ void xfuse_devredir_cb_enum_dir_done_TODO(void *vp, tui32 IoStatus) 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_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_size = xinode->size; e.attr.st_atime = xinode->atime; e.attr.st_mtime = xinode->mtime; e.attr.st_ctime = xinode->ctime; @@ -1984,7 +2043,7 @@ static void xfuse_cb_getattr(fuse_req_t req, fuse_ino_t ino, xino = g_xrdp_fs.inode_table[ino]; memset(&stbuf, 0, sizeof(stbuf)); - stbuf.st_ino = ino; + stbuf.st_ino = ino; stbuf.st_mode = xino->mode; stbuf.st_nlink = xino->nlink; stbuf.st_size = xino->size; @@ -2096,7 +2155,10 @@ static void xfuse_cb_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, do_remote_lookup: + xfuse_mark_as_stale((int) ino); + log_debug("did not find entry; redirecting call to dev_redir"); + device_id = xfuse_get_device_id_for_inode((tui32) ino, full_path); log_debug("dev_id=%d ino=%d full_path=%s", device_id, ino, full_path); @@ -2925,4 +2987,73 @@ static void xfuse_cb_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr, fuse_reply_attr(req, &st, 1.0); /* LK_TODO just faking for now */ } +/****************************************************************************** + * miscellaneous functions + *****************************************************************************/ + +/** + * Mark all files with matching parent inode as stale + * + * @param pinode the parent inode + *****************************************************************************/ + +static void +xfuse_mark_as_stale(int pinode) +{ + int i; + XRDP_INODE *xinode; + + if ((pinode < FIRST_INODE) || (pinode >= g_xrdp_fs.num_entries)) + return; + + for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++) + { + if ((xinode = g_xrdp_fs.inode_table[i]) == NULL) + continue; + + /* match parent inode */ + if (xinode->parent_inode != pinode) + continue; + + /* got a match */ + xinode->stale = 1; + } +} + +/** + * Delete all files with matching parent inode that are marked as stale + * + * @param pinode the parent inode + *****************************************************************************/ + +static void +xfuse_delete_stale_entries(int pinode) +{ + int i; + XRDP_INODE *xinode; + + if ((pinode < FIRST_INODE) || (pinode >= g_xrdp_fs.num_entries)) + return; + + for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++) + { + if ((xinode = g_xrdp_fs.inode_table[i]) == NULL) + continue; + + /* match parent inode */ + if (xinode->parent_inode != pinode) + continue; + + /* got a match, but is it stale? */ + if (!xinode->stale) + continue; + + /* ok to delete */ + if (xinode->mode & S_IFREG) + xfuse_delete_file_with_xinode(xinode); + else + xfuse_recursive_delete_dir_with_xinode(xinode); + } +} + #endif /* end else #ifndef XRDP_FUSE */ diff --git a/sesman/chansrv/chansrv_fuse.h b/sesman/chansrv/chansrv_fuse.h index 364c1d94..09011452 100644 --- a/sesman/chansrv/chansrv_fuse.h +++ b/sesman/chansrv/chansrv_fuse.h @@ -41,6 +41,7 @@ struct xrdp_inode int lindex; /* used in clipboard operations */ int is_loc_resource; /* this is not a redirected resource */ int close_in_progress; /* close cmd sent to client */ + int stale; /* mark file as stale, ok to remove */ }; typedef struct xrdp_inode XRDP_INODE; // LK_TODO use this instead of using struct xrdp_inode