Merge branch 'fuse_speedup'

ulab-next
Laxmikant Rashinkar 12 years ago
commit ef32626a9b

@ -41,7 +41,7 @@
* *
*/ */
// LK_TODO #define USE_SYNC_FLAG //#define USE_SYNC_FLAG
/* FUSE mount point */ /* FUSE mount point */
char g_fuse_root_path[256] = ""; char g_fuse_root_path[256] = "";
@ -139,7 +139,7 @@ void xfuse_devredir_cb_file_close(void *vp) {}
#define log_debug(_params...) \ #define log_debug(_params...) \
{ \ { \
if (LOG_DEBUG <= LOG_LEVEL) \ if (LOG_DEBUG <= LOG_LEVEL) \
{ \ { \
g_write("[%10.10u]: FUSE %s: %d : ", \ g_write("[%10.10u]: FUSE %s: %d : ", \
g_time3(), __func__, __LINE__); \ g_time3(), __func__, __LINE__); \
@ -164,6 +164,13 @@ struct dirbuf
size_t size; size_t size;
}; };
struct dirbuf1
{
char buf[4096];
int bytes_in_buf;
int first_time;
};
/* FUSE reply types */ /* FUSE reply types */
#define RT_FUSE_REPLY_OPEN 1 #define RT_FUSE_REPLY_OPEN 1
#define RT_FUSE_REPLY_CREATE 2 #define RT_FUSE_REPLY_CREATE 2
@ -181,6 +188,9 @@ struct xfuse_info
int reply_type; int reply_type;
int mode; int mode;
int type; int type;
size_t size;
off_t off;
struct dirbuf1 dirbuf1;
}; };
typedef struct xfuse_info XFUSE_INFO; typedef struct xfuse_info XFUSE_INFO;
@ -227,10 +237,13 @@ static struct xrdp_inode * xfuse_create_file_in_xrdp_fs(tui32 device_id,
int pinode, char *name, int pinode, char *name,
int type); int type);
static int xfuse_does_file_exist(int parent, char *name); static int xfuse_does_file_exist(int parent, char *name);
static int xfuse_delete_file(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_file_with_xinode(XRDP_INODE *xinode);
static int xfuse_delete_dir_with_xinode(XRDP_INODE *xinode); static int xfuse_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);
/* forward declarations for calls we make into devredir */ /* forward declarations for calls we make into devredir */
int dev_redir_get_dir_listing(void *fusep, tui32 device_id, char *path); int dev_redir_get_dir_listing(void *fusep, tui32 device_id, char *path);
@ -255,6 +268,9 @@ static void xfuse_cb_getattr(fuse_req_t req, fuse_ino_t ino,
static void xfuse_dirbuf_add(fuse_req_t req, struct dirbuf *b, static void xfuse_dirbuf_add(fuse_req_t req, struct dirbuf *b,
const char *name, fuse_ino_t ino); const char *name, fuse_ino_t ino);
static int xfuse_dirbuf_add1(fuse_req_t req, struct dirbuf1 *b,
const char *name, fuse_ino_t ino);
static void xfuse_cb_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, static void xfuse_cb_readdir(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);
@ -410,6 +426,10 @@ int xfuse_init()
#if 0 #if 0
sprintf(opt, "-o uid=%d,gid=%d", g_getuid(), g_getgid()); sprintf(opt, "-o uid=%d,gid=%d", g_getuid(), g_getgid());
fuse_opt_add_arg(&args, opt); fuse_opt_add_arg(&args, opt);
#else
/* disable multi threading */
sprintf(opt, "-s");
fuse_opt_add_arg(&args, opt);
#endif #endif
if (xfuse_init_lib(&args)) if (xfuse_init_lib(&args))
@ -548,12 +568,6 @@ int xfuse_create_share(tui32 device_id, char *dirname)
return -1; return -1;
} }
if ((fip = calloc(1, sizeof(XFUSE_INFO))) == NULL)
{
log_error("system out of memory");
return -1;
}
/* create directory entry */ /* create directory entry */
xinode->parent_inode = 1; xinode->parent_inode = 1;
xinode->inode = g_xrdp_fs.next_node++; xinode->inode = g_xrdp_fs.next_node++;
@ -582,6 +596,13 @@ int xfuse_create_share(tui32 device_id, char *dirname)
return -1; return -1;
xinode->nentries++; xinode->nentries++;
#if 0
if ((fip = calloc(1, sizeof(XFUSE_INFO))) == NULL)
{
log_error("system out of memory");
return -1;
}
/* 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; // LK_TODO saved_inode;
@ -590,6 +611,7 @@ int xfuse_create_share(tui32 device_id, char *dirname)
fip->device_id = device_id; fip->device_id = device_id;
dev_redir_get_dir_listing((void *) fip, device_id, "\\"); dev_redir_get_dir_listing((void *) fip, device_id, "\\");
#endif
return 0; return 0;
} }
@ -652,14 +674,6 @@ int xfuse_file_contents_size(int stream_id, int file_size)
static int xfuse_init_lib(struct fuse_args *args) static int xfuse_init_lib(struct fuse_args *args)
{ {
// LK_TODO
{
int 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) if (fuse_parse_cmdline(args, &g_mount_point, 0, 0) < 0)
{ {
log_error("fuse_parse_cmdline() failed"); log_error("fuse_parse_cmdline() failed");
@ -785,7 +799,7 @@ static int xfuse_init_xrdp_fs()
xino->ctime = time(0); xino->ctime = time(0);
strcpy(xino->name, ".clipboard"); strcpy(xino->name, ".clipboard");
g_xrdp_fs.max_entries = 1024; g_xrdp_fs.max_entries = 4096;
g_xrdp_fs.num_entries = 3; g_xrdp_fs.num_entries = 3;
g_xrdp_fs.next_node = 3; g_xrdp_fs.next_node = 3;
@ -865,6 +879,7 @@ static void xfuse_create_file(fuse_req_t req, fuse_ino_t parent,
/* 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;
xfuse_update_xrdpfs_size();
log_debug("inserted new dir at inode_table[%d]", (int) xinode->inode); log_debug("inserted new dir at inode_table[%d]", (int) xinode->inode);
xfuse_dump_fs(); xfuse_dump_fs();
@ -1064,7 +1079,7 @@ static struct xrdp_inode * xfuse_create_file_in_xrdp_fs(tui32 device_id,
log_debug("S_IFDIR=0x%x S_IFREG=0x%x type=0x%x", S_IFDIR, S_IFREG, type); 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++; /* TODO should be thread safe */ xinode->inode = g_xrdp_fs.next_node++;
xinode->nlink = 1; xinode->nlink = 1;
xinode->uid = getuid(); xinode->uid = getuid();
xinode->gid = getgid(); xinode->gid = getgid();
@ -1087,13 +1102,14 @@ static struct xrdp_inode * xfuse_create_file_in_xrdp_fs(tui32 device_id,
} }
g_xrdp_fs.inode_table[xinode->inode] = xinode; g_xrdp_fs.inode_table[xinode->inode] = xinode;
g_xrdp_fs.num_entries++; /* TODO should be thread safe */ g_xrdp_fs.num_entries++;
/* bump up lookup count in parent dir */ /* bump up lookup count in parent dir */
xinodep = g_xrdp_fs.inode_table[pinode]; xinodep = g_xrdp_fs.inode_table[pinode];
xinodep->nentries++; xinodep->nentries++;
xfuse_update_xrdpfs_size();
log_debug("LK_TODO: incremented nentries; parent=%d nentries=%d", log_debug("incremented nentries; parent=%d nentries=%d",
pinode, xinodep->nentries); pinode, xinodep->nentries);
/* LK_TODO */ /* LK_TODO */
@ -1181,6 +1197,85 @@ static int xfuse_delete_dir_with_xinode(XRDP_INODE *xinode)
return 0; return 0;
} }
static void xfuse_update_xrdpfs_size()
{
void *vp;
int diff;
diff = g_xrdp_fs.max_entries - g_xrdp_fs.num_entries;
if (diff > 100)
return;
/* extend memory */
vp = realloc(g_xrdp_fs.inode_table,
(g_xrdp_fs.max_entries + 100) * sizeof(struct xrdp_inode *));
if (vp == NULL)
{
log_error("system out of memory");
return;
}
/* zero newly added memory */
memset(vp + g_xrdp_fs.max_entries * sizeof(struct xrdp_inode *),
0,
100 * sizeof(struct xrdp_inode *));
g_xrdp_fs.max_entries += 100;
g_xrdp_fs.inode_table = vp;
}
static void xfuse_enum_dir(fuse_req_t req, fuse_ino_t ino, size_t size,
off_t off, struct fuse_file_info *fi)
{
XRDP_INODE *xinode;
XRDP_INODE *xinode1;
struct dirbuf b;
int first_time = 1;
int i;
memset(&b, 0, sizeof(struct dirbuf));
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 != ino)
continue;
if (first_time)
{
first_time = 0;
if (ino == 1)
{
xfuse_dirbuf_add(req, &b, ".", 1);
xfuse_dirbuf_add(req, &b, "..", 1);
}
else
{
xinode1 = g_xrdp_fs.inode_table[ino];
xfuse_dirbuf_add(req, &b, ".", ino);
xfuse_dirbuf_add(req, &b, "..", xinode1->parent_inode);
}
}
xfuse_dirbuf_add(req, &b, xinode->name, xinode->inode);
}
if (!first_time)
{
if (off < b.size)
fuse_reply_buf(req, b.p + off, min(b.size - off, size));
else
fuse_reply_buf(req, NULL, 0);
}
if (b.p)
free(b.p);
}
/****************************************************************************** /******************************************************************************
** ** ** **
** callbacks for devredir ** ** callbacks for devredir **
@ -1191,47 +1286,63 @@ static int xfuse_delete_dir_with_xinode(XRDP_INODE *xinode)
* Add a file or directory to xrdp file system * Add a file or directory to xrdp file system
*****************************************************************************/ *****************************************************************************/
void xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode) /* LK_TODO delete this after testing */
#if 0
void ___xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode)
{ {
XFUSE_INFO *fip = (XFUSE_INFO *) vp; XFUSE_INFO *fip = (XFUSE_INFO *) vp;
XRDP_INODE *target_inode; XRDP_INODE *xip = NULL;
log_debug("<<<<<< entered");
if ((fip == NULL) || (xinode == NULL)) if ((fip == NULL) || (xinode == NULL))
{ {
log_error("fip or xinode are NULL"); log_error("fip or xinode are NULL");
printf("RASH_TODO: fip or xinode are NULL - leaving\n");
return; return;
} }
/* LK_TODO */ log_debug("req=%p", fip->req);
#if 0
/* do we have a valid inode? */ /* do we have a valid inode? */
if (!xfuse_is_inode_valid(fip->inode)) if (!xfuse_is_inode_valid(fip->inode))
{ {
log_error("inode %d is not valid", fip->inode); log_error("inode %d is not valid", fip->inode);
printf("RASH_TODO: inode %d is not valid - leaving\n", (tui32) fip->inode);
return; return;
} }
#endif
/* if filename is . or .. don't add it */ /* if filename is . or .. don't add it */
if ((strcmp(xinode->name, ".") == 0) || (strcmp(xinode->name, "..") == 0)) if ((strcmp(xinode->name, ".") == 0) || (strcmp(xinode->name, "..") == 0))
{ {
free(xinode); free(xinode);
printf("RASH_TODO: not adding ./.. - leaving\n");
return; return;
} }
// LK_TODO
#if 0
/* we have a parent inode and a dir name; what we need is the xinode */ /* we have a parent inode and a dir name; what we need is the xinode */
/* that matches the parent inode and the dir name */ /* that matches the parent inode and the dir name */
target_inode = xfuse_get_inode_from_pinode_name(fip->inode, fip->name); target_inode = xfuse_get_inode_from_pinode_name(fip->inode, fip->name);
if (target_inode == 0) if (target_inode == 0)
{
log_debug("did not find entry with inode=%d name=%s",
fip->inode, fip->name);
return; return;
}
#endif
if (xfuse_does_file_exist(target_inode->inode, xinode->name)) if ((xip = xfuse_get_inode_from_pinode_name(fip->inode, xinode->name)) != NULL)
{ {
log_debug("inode=%d name=%s already exists in xrdp_fs; not adding it",
fip->inode, xinode->name);
free(xinode); free(xinode);
return; xinode = xip;
goto update_fuse;
} }
xinode->parent_inode = target_inode->inode; xinode->parent_inode = fip->inode;
xinode->inode = g_xrdp_fs.next_node++; xinode->inode = g_xrdp_fs.next_node++;
xinode->uid = getuid(); xinode->uid = getuid();
xinode->gid = getgid(); xinode->gid = getgid();
@ -1239,21 +1350,230 @@ void xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode)
g_xrdp_fs.num_entries++; g_xrdp_fs.num_entries++;
/* insert it in xrdp fs */ /* 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;
xfuse_update_xrdpfs_size();
/* bump up lookup count */ update_fuse:
xinode = g_xrdp_fs.inode_table[target_inode->inode];
xinode->nentries++;
log_debug("added %s to pinode=%d, nentries=%d target_inode->inode=%d", #if 1
fip->name, fip->inode, xinode->nentries, target_inode->inode); /* let FUSE know about this entry */
if (fip->invoke_fuse)
{
struct dirbuf b;
memset(&b, 0, sizeof(struct dirbuf));
/* RASH_TODO if we are not using dirbuf, change this code */
if (fip->dirbuf == NULL)
{
fip->dirbuf = calloc(1, sizeof(struct dirbuf));
xfuse_dirbuf_add(fip->req, &b, ".", xinode->inode);
xfuse_dirbuf_add(fip->req, &b, "..", xinode->parent_inode);
}
xfuse_dirbuf_add(fip->req, &b, xinode->name, xinode->inode);
if (fip->off < b.size)
{
printf("RASH_TODO: xfuse_devredir_cb_enum_dir(): req=%p off=%d\n",
fip->req, (tui32) fip->off);
printf("RASH_TODO: xfuse_devredir_cb_enum_dir(): dumping req b4\n\n");
g_hexdump((char *) fip->req, 128);
printf("RASH_TODO: xfuse_devredir_cb_enum_dir(): dumping buf b4\n\n");
g_hexdump(b.p, b.size);
printf("RASH_TODO: xfuse_devredir_cb_enum_dir(): calling fuse\n");
fuse_reply_buf(fip->req, b.p, b.size);
printf("RASH_TODO: xfuse_devredir_cb_enum_dir(): calling fuse...done\n");
printf("RASH_TODO: xfuse_devredir_cb_enum_dir(): dumping req aft\n\n");
g_hexdump((char *) fip->req, 128);
printf("RASH_TODO: xfuse_devredir_cb_enum_dir(): dumping buf aft\n\n");
g_hexdump(b.p, b.size);
}
else
{
printf("RASH_TODO: xfuse_devredir_cb_enum_dir(): calling fuse with NULL\n");
fuse_reply_buf(fip->req, NULL, 0);
printf("RASH_TODO: xfuse_devredir_cb_enum_dir(): calling fuse with NULL...done\n");
}
log_debug("added inode=%d name=%s to FUSE", (tui32) xinode->inode, xinode->name);
}
#endif
log_debug("leaving");
printf("RASH_TODO: xfuse_devredir_cb_enum_dir(): leaving\n");
}
#endif
void xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode)
{
XFUSE_INFO *fip = (XFUSE_INFO *) vp;
XRDP_INODE *xip = NULL;
if ((fip == NULL) || (xinode == NULL))
{
log_error("fip or xinode are NULL");
return;
}
if (!xfuse_is_inode_valid(fip->inode))
{
log_error("inode %d is not valid", fip->inode);
return;
}
/* if filename is . or .. don't add it */
if ((strcmp(xinode->name, ".") == 0) || (strcmp(xinode->name, "..") == 0))
{
free(xinode);
return;
}
if ((xip = xfuse_get_inode_from_pinode_name(fip->inode, xinode->name)) != NULL)
{
log_debug("inode=%d name=%s already exists in xrdp_fs; not adding it",
fip->inode, xinode->name);
free(xinode);
xinode = xip;
return;
}
xinode->parent_inode = fip->inode;
xinode->inode = g_xrdp_fs.next_node++;
xinode->uid = getuid();
xinode->gid = getgid();
xinode->device_id = fip->device_id;
g_xrdp_fs.num_entries++;
/* insert it in xrdp fs and update lookup count */
g_xrdp_fs.inode_table[xinode->inode] = xinode;
g_xrdp_fs.inode_table[fip->inode]->nentries;
xfuse_update_xrdpfs_size();
} }
/** /**
*****************************************************************************/ *****************************************************************************/
void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus) void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus)
{
log_debug(">>>>>> vp=%p IoStatus=0x%x", vp, IoStatus);
if (vp == NULL)
return;
XRDP_INODE *xinode;
XRDP_INODE *ti;
struct dirbuf1 b;
int i;
int first_time = 1;
XFUSE_INFO *fip = (XFUSE_INFO *) vp;
if (fip == NULL)
{
log_debug("fip is NULL");
goto done;
}
if (IoStatus != 0)
{
/* command failed */
if (fip->invoke_fuse)
fuse_reply_err(fip->req, ENOENT);
goto done;
}
/* do we have a valid inode? */
if (!xfuse_is_inode_valid(fip->inode))
{
log_error("inode %d is not valid", fip->inode);
if (fip->invoke_fuse)
fuse_reply_err(fip->req, EBADF);
goto done;
}
#if 0
memset(&b, 0, sizeof(struct dirbuf));
#else
b.bytes_in_buf = 0;
#endif
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 != fip->inode)
continue;
xinode->is_synced = 1;
if (first_time)
{
first_time = 0;
ti = g_xrdp_fs.inode_table[fip->inode];
#if 0
xfuse_dirbuf_add(fip->req, &b, ".", fip->inode);
xfuse_dirbuf_add(fip->req, &b, "..", ti->parent_inode);
#else
xfuse_dirbuf_add1(fip->req, &b, ".", fip->inode);
xfuse_dirbuf_add1(fip->req, &b, "..", ti->parent_inode);
#endif
}
#if 0
xfuse_dirbuf_add(fip->req, &b, xinode->name, xinode->inode);
#else
xfuse_dirbuf_add1(fip->req, &b, xinode->name, xinode->inode);
#endif
}
if ((first_time == 0) && (fip->invoke_fuse))
{
if (fip->off < b.bytes_in_buf)
{
#if 0
fuse_reply_buf(fip->req, b.p + fip->off,
min(b.size - fip->off, fip->size));
#else
fuse_reply_buf(fip->req, b.buf, b.bytes_in_buf);
#endif
fuse_reply_buf(fip->req, NULL, 0);
}
else
{
fuse_reply_buf(fip->req, NULL, 0);
}
}
else
{
fuse_reply_err(fip->req, ENOENT);
}
done:
#if 0
if (b.p)
free(b.p);
#endif
if (!fip)
printf("###### %s : %s : %d: fip is NULL\n", __FILE__, __func__, __LINE__);
if (fip)
free(fip);
}
void xfuse_devredir_cb_enum_dir_done_TODO(void *vp, tui32 IoStatus)
{ {
struct xrdp_inode *xinode; struct xrdp_inode *xinode;
struct fuse_entry_param e; struct fuse_entry_param e;
@ -1261,6 +1581,8 @@ void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus)
XFUSE_INFO *fip = (XFUSE_INFO *) vp; XFUSE_INFO *fip = (XFUSE_INFO *) vp;
printf("--------- xfuse_devredir_cb_enum_dir_done() entered\n");
xfuse_dump_fs(); xfuse_dump_fs();
if (fip == NULL) if (fip == NULL)
@ -1598,6 +1920,49 @@ void xfuse_devredir_cb_file_close(void *vp)
*****************************************************************************/ *****************************************************************************/
static void xfuse_cb_lookup(fuse_req_t req, fuse_ino_t parent, const char *name) static void xfuse_cb_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
{
XRDP_INODE *xinode;
struct fuse_entry_param e;
log_debug("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;
}
xinode = xfuse_get_inode_from_pinode_name(parent, name);
if (xinode == NULL)
{
log_debug("did not find entry for parent=%d name=%s", parent, name);
fuse_reply_err(req, ENOENT);
return;
}
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 for parent=%d name=%s", parent, name);
return;
}
static void xfuse_cb_lookup_TODO(fuse_req_t req, fuse_ino_t parent, const char *name)
{ {
XFUSE_INFO *fip; XFUSE_INFO *fip;
XRDP_INODE *xinode; XRDP_INODE *xinode;
@ -1606,6 +1971,9 @@ static void xfuse_cb_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
char full_path[4096]; char full_path[4096];
char *cptr; 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); log_debug("ENTERED: looking for parent=%d name=%s", (int) parent, name);
xfuse_dump_fs(); xfuse_dump_fs();
@ -1619,7 +1987,7 @@ static void xfuse_cb_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
if ((xinode = xfuse_get_inode_from_pinode_name(parent, name)) != NULL) if ((xinode = xfuse_get_inode_from_pinode_name(parent, name)) != NULL)
{ {
log_debug("LK_TODO: got match: device_id=%d", xinode->device_id); log_debug("got match: device_id=%d", xinode->device_id);
/* got a full match; if this dir is located on a remote device */ /* got a full match; if this dir is located on a remote device */
/* and is not synced, do a remote look up */ /* and is not synced, do a remote look up */
@ -1659,13 +2027,15 @@ do_remote_lookup:
/* if ino belongs to a redirected share, pass the call to devredir; */ /* if ino belongs to a redirected share, pass the call to devredir; */
/* when done, devredir will invoke xfuse_devredir_cb_enum_dir_done(...) */ /* when done, devredir will invoke xfuse_devredir_cb_enum_dir_done(...) */
strcpy(full_path, name); strcpy(full_path, name);
log_debug("LK_TODO: full_path=%s name=%s", 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); device_id = xfuse_get_device_id_for_inode((tui32) parent, full_path);
log_debug("device_id=%d", device_id); log_debug("device_id=%d", device_id);
if (device_id != 0) if (device_id != 0)
{ {
log_debug("did not find entry; redirecting call to dev_redir"); 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) if ((fip = calloc(1, sizeof(XFUSE_INFO))) == NULL)
{ {
log_error("system out of memory"); log_error("system out of memory");
@ -1729,7 +2099,7 @@ static void xfuse_cb_getattr(fuse_req_t req, fuse_ino_t ino,
(void) fi; (void) fi;
log_debug("ino=%d", (int) ino); log_debug("req=%p ino=%d", req, (int) ino);
/* if ino is not valid, just return */ /* if ino is not valid, just return */
if (!xfuse_is_inode_valid(ino)) if (!xfuse_is_inode_valid(ino))
@ -1740,7 +2110,6 @@ static void xfuse_cb_getattr(fuse_req_t req, fuse_ino_t ino,
} }
xino = g_xrdp_fs.inode_table[ino]; xino = g_xrdp_fs.inode_table[ino];
xfuse_dump_xrdp_inode(xino);
memset(&stbuf, 0, sizeof(stbuf)); memset(&stbuf, 0, sizeof(stbuf));
stbuf.st_ino = ino; stbuf.st_ino = ino;
@ -1749,6 +2118,7 @@ static void xfuse_cb_getattr(fuse_req_t req, fuse_ino_t ino,
stbuf.st_size = xino->size; stbuf.st_size = xino->size;
fuse_reply_attr(req, &stbuf, 1.0); fuse_reply_attr(req, &stbuf, 1.0);
log_debug("exiting");
} }
/** /**
@ -1772,12 +2142,209 @@ static void xfuse_dirbuf_add(fuse_req_t req, struct dirbuf *b,
b->size); b->size);
} }
static int xfuse_dirbuf_add1(fuse_req_t req, struct dirbuf1 *b,
const char *name, fuse_ino_t ino)
{
struct stat stbuf;
int len;
len = fuse_add_direntry(req, NULL, 0, name, NULL, 0);
if (b->bytes_in_buf + len > 4096)
{
log_debug("not adding entry because dirbuf overflow would occur");
return -1;
}
memset(&stbuf, 0, sizeof(stbuf));
stbuf.st_ino = ino;
fuse_add_direntry(req,
&b->buf[b->bytes_in_buf], /* index where new entry will be added to buf */
4096 - len, /* remaining size of buf */
name, /* name of entry */
&stbuf, /* file attributes */
b->bytes_in_buf + len /* offset of next entry */
);
b->bytes_in_buf += len;
return 0;
}
/** /**
* *
*****************************************************************************/ *****************************************************************************/
static void xfuse_cb_readdir(fuse_req_t req, fuse_ino_t ino, size_t size, static void xfuse_cb_readdir(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)
{
XRDP_INODE *xinode;
XFUSE_INFO *fip;
tui32 device_id;
char full_path[4096];
char *cptr;
log_debug("req=%p inode=%d size=%d offset=%d", req, ino, size, off);
if (!xfuse_is_inode_valid(ino))
{
log_error("inode %d is not valid", ino);
fuse_reply_err(req, EBADF);
return;
}
xinode = g_xrdp_fs.inode_table[ino];
if (xinode->device_id == 0)
{
/* enumerate local resources */
xfuse_enum_dir(req, ino, size, off, fi);
return;
}
/* 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
if (xinode->is_synced)
{
xfuse_enum_dir(req, ino, size, off, fi);
return;
}
else
{
goto do_remote_lookup;
}
#endif
do_remote_lookup:
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);
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 = ino;
fip->size = size;
fip->off = off;
fip->fi = fi;
fip->dirbuf1.first_time = 1;
fip->dirbuf1.bytes_in_buf = 0;
fip->invoke_fuse = 1;
fip->device_id = device_id;
/* 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
{
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);
}
}
}
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 xrdp_inode *xinode;
struct dirbuf b; struct dirbuf b;
@ -1785,6 +2352,9 @@ static void xfuse_cb_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
(void) fi; (void) fi;
/* SPEEDUP_TODO */
printf("++++++ cb_readdir: looking for inode=%d\n", (int) ino);
log_debug("looking for dir with inode=%d", ino); log_debug("looking for dir with inode=%d", ino);
if (!xfuse_is_inode_valid(ino)) if (!xfuse_is_inode_valid(ino))
@ -1823,6 +2393,8 @@ static void xfuse_cb_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
fuse_reply_buf(req, NULL, 0); fuse_reply_buf(req, NULL, 0);
free(b.p); free(b.p);
printf("++++++ cb_readdir: leaving\n");
} }
/** /**
@ -2132,7 +2704,7 @@ static void xfuse_create_dir_or_file(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, int type) struct fuse_file_info *fi, int type)
{ {
XFUSE_INFO *fip; // LK_TODO use only XFUSE_INFO instead of struct XFUSE_INFO *fip;
char *cptr; char *cptr;
char full_path[1024]; char full_path[1024];
tui32 device_id; tui32 device_id;

@ -381,7 +381,7 @@ int dev_redir_send_drive_create_request(tui32 device_id, char *path,
int bytes; int bytes;
int len; int len;
log_debug("LK_TODO: DesiredAccess=0x%x CreateDisposition=0x%x CreateOptions=0x%x", log_debug("DesiredAccess=0x%x CreateDisposition=0x%x CreateOptions=0x%x",
DesiredAccess, CreateDisposition, CreateOptions); DesiredAccess, CreateDisposition, CreateOptions);
/* to store path as unicode */ /* to store path as unicode */
@ -482,7 +482,11 @@ void dev_redir_send_drive_dir_request(IRP *irp, tui32 device_id,
IRP_MJ_DIRECTORY_CONTROL, IRP_MJ_DIRECTORY_CONTROL,
IRP_MN_QUERY_DIRECTORY); IRP_MN_QUERY_DIRECTORY);
#ifdef USE_SHORT_NAMES_IN_DIR_LISTING
stream_wr_u32_le(s, FileBothDirectoryInformation); /* FsInformationClass */
#else
stream_wr_u32_le(s, FileDirectoryInformation); /* FsInformationClass */ stream_wr_u32_le(s, FileDirectoryInformation); /* FsInformationClass */
#endif
stream_wr_u8(s, InitialQuery); /* InitialQuery */ stream_wr_u8(s, InitialQuery); /* InitialQuery */
if (!InitialQuery) if (!InitialQuery)
@ -651,8 +655,7 @@ void dev_redir_proc_device_iocompletion(struct stream *s)
/* LK_TODO need to check for IoStatus */ /* LK_TODO need to check for IoStatus */
log_debug("entered: IoStatus=0x%x CompletionId=%d", log_debug("entered: IoStatus=0x%x CompletionId=%d", IoStatus, CompletionId);
IoStatus, CompletionId);
if ((irp = dev_redir_irp_find(CompletionId)) == NULL) if ((irp = dev_redir_irp_find(CompletionId)) == NULL)
{ {
@ -682,6 +685,7 @@ void dev_redir_proc_device_iocompletion(struct stream *s)
stream_rd_u32_le(s, irp->FileId); stream_rd_u32_le(s, irp->FileId);
log_debug("got CID_CREATE_DIR_REQ IoStatus=0x%x FileId=%d", log_debug("got CID_CREATE_DIR_REQ IoStatus=0x%x FileId=%d",
IoStatus, irp->FileId); IoStatus, irp->FileId);
dev_redir_send_drive_dir_request(irp, DeviceId, 1, irp->pathname); dev_redir_send_drive_dir_request(irp, DeviceId, 1, irp->pathname);
break; break;
@ -788,6 +792,12 @@ void dev_redir_proc_query_dir_response(IRP *irp,
tui32 FileNameLength; tui32 FileNameLength;
tui32 status; tui32 status;
#ifdef USE_SHORT_NAMES_IN_DIR_LISTING
tui32 EaSize;
tui8 ShortNameLength;
tui8 Reserved;
#endif
char filename[256]; char filename[256];
int i = 0; int i = 0;
@ -828,18 +838,30 @@ void dev_redir_proc_query_dir_response(IRP *irp,
stream_rd_u32_le(s_in, FileAttributes); stream_rd_u32_le(s_in, FileAttributes);
stream_rd_u32_le(s_in, FileNameLength); stream_rd_u32_le(s_in, FileNameLength);
#ifdef USE_SHORT_NAMES_IN_DIR_LISTING
stream_rd_u32_le(s_in, EaSize);
stream_rd_u8(s_in, ShortNameLength);
stream_rd_u8(s_in, Reserved);
stream_seek(s_in, 23); /* ShortName in Unicode */
#endif
devredir_cvt_from_unicode_len(filename, s_in->p, FileNameLength); devredir_cvt_from_unicode_len(filename, s_in->p, FileNameLength);
#ifdef USE_SHORT_NAMES_IN_DIR_LISTING
i += 70 + 23 + FileNameLength;
#else
i += 64 + FileNameLength; i += 64 + FileNameLength;
#endif
log_debug("NextEntryOffset: 0x%x", NextEntryOffset); //log_debug("NextEntryOffset: 0x%x", NextEntryOffset);
log_debug("CreationTime: 0x%llx", CreationTime); //log_debug("CreationTime: 0x%llx", CreationTime);
log_debug("LastAccessTime: 0x%llx", LastAccessTime); //log_debug("LastAccessTime: 0x%llx", LastAccessTime);
log_debug("LastWriteTime: 0x%llx", LastWriteTime); //log_debug("LastWriteTime: 0x%llx", LastWriteTime);
log_debug("ChangeTime: 0x%llx", ChangeTime); //log_debug("ChangeTime: 0x%llx", ChangeTime);
log_debug("EndOfFile: %lld", EndOfFile); //log_debug("EndOfFile: %lld", EndOfFile);
log_debug("FileAttributes: 0x%x", FileAttributes); //log_debug("FileAttributes: 0x%x", FileAttributes);
log_debug("FileNameLength: 0x%x", FileNameLength); #ifdef USE_SHORT_NAMES_IN_DIR_LISTING
//log_debug("ShortNameLength: %d", ShortNameLength);
#endif
//log_debug("FileNameLength: %d", FileNameLength);
log_debug("FileName: %s", filename); log_debug("FileName: %s", filename);
if ((xinode = calloc(1, sizeof(struct xrdp_inode))) == NULL) if ((xinode = calloc(1, sizeof(struct xrdp_inode))) == NULL)
@ -886,6 +908,9 @@ int dev_redir_get_dir_listing(void *fusep, tui32 device_id, char *path)
if ((irp = dev_redir_irp_new()) == NULL) if ((irp = dev_redir_irp_new()) == NULL)
return -1; return -1;
/* cvt / to windows compatible \ */
devredir_cvt_slash(path);
irp->completion_id = g_completion_id++; irp->completion_id = g_completion_id++;
irp->completion_type = CID_CREATE_DIR_REQ; irp->completion_type = CID_CREATE_DIR_REQ;
irp->device_id = device_id; irp->device_id = device_id;
@ -895,6 +920,7 @@ int dev_redir_get_dir_listing(void *fusep, tui32 device_id, char *path)
DesiredAccess = DA_FILE_READ_DATA | DA_SYNCHRONIZE; DesiredAccess = DA_FILE_READ_DATA | DA_SYNCHRONIZE;
CreateOptions = CO_FILE_DIRECTORY_FILE | CO_FILE_SYNCHRONOUS_IO_NONALERT; CreateOptions = CO_FILE_DIRECTORY_FILE | CO_FILE_SYNCHRONOUS_IO_NONALERT;
CreateDisposition = CD_FILE_OPEN; CreateDisposition = CD_FILE_OPEN;
rval = dev_redir_send_drive_create_request(device_id, path, rval = dev_redir_send_drive_create_request(device_id, path,
DesiredAccess, CreateOptions, DesiredAccess, CreateOptions,
CreateDisposition, CreateDisposition,
@ -905,7 +931,6 @@ int dev_redir_get_dir_listing(void *fusep, tui32 device_id, char *path)
/* when we get a respone to dev_redir_send_drive_create_request(), we */ /* when we get a respone to dev_redir_send_drive_create_request(), we */
/* call dev_redir_send_drive_dir_request(), which needs the following */ /* call dev_redir_send_drive_dir_request(), which needs the following */
/* at the end of the path argument */ /* at the end of the path argument */
if (dev_redir_string_ends_with(irp->pathname, '\\')) if (dev_redir_string_ends_with(irp->pathname, '\\'))
strcat(irp->pathname, "*"); strcat(irp->pathname, "*");
else else
@ -964,7 +989,7 @@ int dev_redir_file_open(void *fusep, tui32 device_id, char *path,
} }
else //if (mode & O_RDWR) else //if (mode & O_RDWR)
{ {
log_debug("LK_TODO: open file in O_RDWR"); log_debug("open file in O_RDWR");
DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA | DA_SYNCHRONIZE; DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA | DA_SYNCHRONIZE;
CreateOptions = CO_FILE_SYNCHRONOUS_IO_NONALERT; CreateOptions = CO_FILE_SYNCHRONOUS_IO_NONALERT;
CreateDisposition = CD_FILE_OPEN; // WAS 1 CreateDisposition = CD_FILE_OPEN; // WAS 1
@ -972,7 +997,7 @@ int dev_redir_file_open(void *fusep, tui32 device_id, char *path,
#if 0 #if 0
else else
{ {
log_debug("LK_TODO: open file in O_RDONLY"); log_debug("open file in O_RDONLY");
DesiredAccess = DA_FILE_READ_DATA | DA_SYNCHRONIZE; DesiredAccess = DA_FILE_READ_DATA | DA_SYNCHRONIZE;
CreateOptions = CO_FILE_SYNCHRONOUS_IO_NONALERT; CreateOptions = CO_FILE_SYNCHRONOUS_IO_NONALERT;
CreateDisposition = CD_FILE_OPEN; CreateDisposition = CD_FILE_OPEN;
@ -1408,6 +1433,22 @@ void dev_redir_insert_dev_io_req_header(struct stream *s,
stream_wr_u32_le(s, MinorFunction); stream_wr_u32_le(s, MinorFunction);
} }
/**
* Convert / to windows compatible \
*****************************************************************************/
void devredir_cvt_slash(char *path)
{
char *cptr = path;
while (*cptr != 0)
{
if (*cptr == '/')
*cptr = '\\';
cptr++;
}
}
void devredir_cvt_to_unicode(char *unicode, char *path) void devredir_cvt_to_unicode(char *unicode, char *path)
{ {
int len = strlen(path); int len = strlen(path);

@ -37,6 +37,8 @@
#include "log.h" #include "log.h"
#include "chansrv_fuse.h" #include "chansrv_fuse.h"
#define USE_SHORT_NAMES_IN_DIR_LISTING
typedef struct fuse_data FUSE_DATA; typedef struct fuse_data FUSE_DATA;
struct fuse_data struct fuse_data
{ {
@ -123,6 +125,7 @@ void dev_redir_insert_dev_io_req_header(struct stream *s,
tui32 MajorFunction, tui32 MajorFunction,
tui32 MinorFunction); tui32 MinorFunction);
void devredir_cvt_slash(char *path);
void devredir_cvt_to_unicode(char *unicode, char *path); void devredir_cvt_to_unicode(char *unicode, char *path);
void devredir_cvt_from_unicode_len(char *path, char *unicode, int len); void devredir_cvt_from_unicode_len(char *path, char *unicode, int len);
int dev_redir_string_ends_with(char *string, char c); int dev_redir_string_ends_with(char *string, char c);

@ -61,7 +61,8 @@ lib=libxup.so
username=ask username=ask
password=ask password=ask
ip=127.0.0.1 ip=127.0.0.1
port=-1 port=/tmp/.xrdp/xrdp_display_10
chansrvport=/tmp/.xrdp/xrdp_chansrv_socket_7210
xserverbpp=24 xserverbpp=24
[xrdp2] [xrdp2]

Loading…
Cancel
Save