Merge pull request #1327 from matt335672/implement-separate-lookup
XFuse file overwrite and lookup improvements
This commit is contained in:
commit
006721fea8
@ -24,7 +24,6 @@
|
|||||||
* 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 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
|
* o in thunar, when I move a file by dragging to another folder, the file
|
||||||
@ -33,12 +32,9 @@
|
|||||||
* o fuse ops to support
|
* o fuse ops to support
|
||||||
* o touch does not work
|
* o touch does not work
|
||||||
* o chmod must work
|
* o chmod must work
|
||||||
* o cat >> file is not working
|
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
//#define USE_SYNC_FLAG
|
|
||||||
|
|
||||||
/* 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 */
|
char g_fuse_clipboard_path[256] = ""; /* for clipboard use */
|
||||||
@ -74,10 +70,17 @@ int xfuse_file_contents_size(int stream_id, int file_size) { r
|
|||||||
int xfuse_add_clip_dir_item(const char *filename, int flags, int size, int lindex) { return 0; }
|
int xfuse_add_clip_dir_item(const char *filename, int flags, int size, int lindex) { return 0; }
|
||||||
int xfuse_create_share(tui32 device_id, const char *dirname) { return 0; }
|
int xfuse_create_share(tui32 device_id, const char *dirname) { return 0; }
|
||||||
void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId, tui32 FileId) {}
|
void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId, tui32 FileId) {}
|
||||||
void xfuse_devredir_cb_write_file(void *vp, const char *buf, size_t length) {}
|
void xfuse_devredir_cb_write_file(void *vp, tui32 IoStatus, const char *buf, size_t length) {}
|
||||||
void xfuse_devredir_cb_read_file(void *vp, const char *buf, size_t length) {}
|
void xfuse_devredir_cb_read_file(void *vp, const char *buf, size_t length) {}
|
||||||
int xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode) { return 0; }
|
struct xrdp_inode *xfuse_devredir_add_file_or_dir(
|
||||||
|
void *vp,
|
||||||
|
const struct file_attr *fattr)
|
||||||
|
{ return NULL;}
|
||||||
void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus) {}
|
void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus) {}
|
||||||
|
void xfuse_devredir_cb_lookup_entry(void *vp,
|
||||||
|
tui32 IoStatus,
|
||||||
|
struct xrdp_inode *xinode)
|
||||||
|
{}
|
||||||
void xfuse_devredir_cb_rmdir_or_file(void *vp, tui32 IoStatus) {}
|
void xfuse_devredir_cb_rmdir_or_file(void *vp, tui32 IoStatus) {}
|
||||||
void xfuse_devredir_cb_rename_file(void *vp, tui32 IoStatus) {}
|
void xfuse_devredir_cb_rename_file(void *vp, tui32 IoStatus) {}
|
||||||
void xfuse_devredir_cb_file_close(void *vp) {}
|
void xfuse_devredir_cb_file_close(void *vp) {}
|
||||||
@ -130,6 +133,9 @@ void xfuse_devredir_cb_file_close(void *vp) {}
|
|||||||
#define LOG_DEBUG 2
|
#define LOG_DEBUG 2
|
||||||
#define LOG_LEVEL LOG_ERROR
|
#define LOG_LEVEL LOG_ERROR
|
||||||
|
|
||||||
|
/* Uncomment for detail of added entries */
|
||||||
|
/* #define XFUSE_DUMP_ADDED_ENTRIES */
|
||||||
|
|
||||||
#define log_error(_params...) \
|
#define log_error(_params...) \
|
||||||
{ \
|
{ \
|
||||||
g_write("[%10.10u]: FUSE %s: %d : ERROR: ", \
|
g_write("[%10.10u]: FUSE %s: %d : ERROR: ", \
|
||||||
@ -166,6 +172,30 @@ void xfuse_devredir_cb_file_close(void *vp) {}
|
|||||||
|
|
||||||
#define OP_RENAME_FILE 0x01
|
#define OP_RENAME_FILE 0x01
|
||||||
|
|
||||||
|
/* a file or dir entry in the xrdp file system */
|
||||||
|
struct xrdp_inode
|
||||||
|
{
|
||||||
|
tui32 parent_inode; /* Parent serial number. */
|
||||||
|
tui32 inode; /* File serial number. */
|
||||||
|
tui32 mode; /* File mode. */
|
||||||
|
tui32 nlink; /* symbolic link count. */
|
||||||
|
tui32 nentries; /* number of entries in a dir */
|
||||||
|
tui32 nopen; /* number of simultaneous opens */
|
||||||
|
tui32 uid; /* User ID of the file's owner. */
|
||||||
|
tui32 gid; /* Group ID of the file's group. */
|
||||||
|
size_t size; /* Size of file, in bytes. */
|
||||||
|
time_t atime; /* Time of last access. */
|
||||||
|
time_t mtime; /* Time of last modification. */
|
||||||
|
time_t ctime; /* Time of last status change. */
|
||||||
|
char name[1024]; /* Dir or filename */
|
||||||
|
tui32 device_id; /* for file system redirection */
|
||||||
|
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
|
||||||
|
|
||||||
/* the xrdp file system in memory */
|
/* the xrdp file system in memory */
|
||||||
struct xrdp_fs
|
struct xrdp_fs
|
||||||
{
|
{
|
||||||
@ -198,16 +228,13 @@ struct xfuse_info
|
|||||||
fuse_req_t req;
|
fuse_req_t req;
|
||||||
fuse_ino_t inode;
|
fuse_ino_t inode;
|
||||||
fuse_ino_t new_inode;
|
fuse_ino_t new_inode;
|
||||||
int invoke_fuse;
|
|
||||||
char name[1024];
|
char name[1024];
|
||||||
char new_name[1024];
|
char new_name[1024];
|
||||||
tui32 device_id;
|
tui32 device_id;
|
||||||
int reply_type;
|
int reply_type; /* RT_FUSE_REPLY_xxx */
|
||||||
int mode;
|
int mode;
|
||||||
int type;
|
int type;
|
||||||
size_t size;
|
size_t size;
|
||||||
off_t off;
|
|
||||||
struct dirbuf1 dirbuf1;
|
|
||||||
};
|
};
|
||||||
typedef struct xfuse_info XFUSE_INFO;
|
typedef struct xfuse_info XFUSE_INFO;
|
||||||
|
|
||||||
@ -272,7 +299,7 @@ static void xfuse_create_file(fuse_req_t req, fuse_ino_t parent,
|
|||||||
|
|
||||||
static void xfuse_dump_fs(void);
|
static void xfuse_dump_fs(void);
|
||||||
static tui32 xfuse_get_device_id_for_inode(fuse_ino_t ino, char *full_path);
|
static tui32 xfuse_get_device_id_for_inode(fuse_ino_t ino, char *full_path);
|
||||||
static void fuse_reverse_pathname(char *full_path, char *reverse_path);
|
static void fuse_reverse_pathname(char *full_path, const char *reverse_path);
|
||||||
|
|
||||||
static struct xrdp_inode * xfuse_get_inode_from_pinode_name(fuse_ino_t pinode,
|
static struct xrdp_inode * xfuse_get_inode_from_pinode_name(fuse_ino_t pinode,
|
||||||
const char *name);
|
const char *name);
|
||||||
@ -287,11 +314,6 @@ static int xfuse_delete_dir_with_xinode(XRDP_INODE *xinode);
|
|||||||
static int xfuse_recursive_delete_dir_with_xinode(XRDP_INODE *xinode);
|
static int xfuse_recursive_delete_dir_with_xinode(XRDP_INODE *xinode);
|
||||||
static void xfuse_update_xrdpfs_size(void);
|
static void xfuse_update_xrdpfs_size(void);
|
||||||
|
|
||||||
#ifdef USE_SYNC_FLAG
|
|
||||||
static void xfuse_enum_dir(fuse_req_t req, fuse_ino_t ino, size_t size,
|
|
||||||
off_t off, struct fuse_file_info *fi);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* 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);
|
||||||
@ -363,6 +385,7 @@ static void xfuse_cb_releasedir(fuse_req_t req, fuse_ino_t ino,
|
|||||||
/* misc calls */
|
/* misc calls */
|
||||||
static void xfuse_mark_as_stale(fuse_ino_t pinode);
|
static void xfuse_mark_as_stale(fuse_ino_t pinode);
|
||||||
static void xfuse_delete_stale_entries(fuse_ino_t pinode);
|
static void xfuse_delete_stale_entries(fuse_ino_t pinode);
|
||||||
|
static void make_fuse_entry_reply(fuse_req_t req, const XRDP_INODE *xinode);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
int
|
int
|
||||||
@ -492,6 +515,14 @@ xfuse_init(void)
|
|||||||
int
|
int
|
||||||
xfuse_deinit(void)
|
xfuse_deinit(void)
|
||||||
{
|
{
|
||||||
|
struct opendir_req *odreq;
|
||||||
|
/* Fail any waiting FUSE requests in the FIFO */
|
||||||
|
while (!fifo_is_empty(&g_fifo_opendir))
|
||||||
|
{
|
||||||
|
odreq = (struct opendir_req *)fifo_remove(&g_fifo_opendir);
|
||||||
|
fuse_reply_err(odreq->req, EBADF);
|
||||||
|
g_free(odreq);
|
||||||
|
}
|
||||||
fifo_deinit(&g_fifo_opendir);
|
fifo_deinit(&g_fifo_opendir);
|
||||||
|
|
||||||
if (g_ch != 0)
|
if (g_ch != 0)
|
||||||
@ -1101,9 +1132,9 @@ static void xfuse_dump_fs(void)
|
|||||||
if ((xinode = g_xrdp_fs.inode_table[i]) == NULL)
|
if ((xinode = g_xrdp_fs.inode_table[i]) == NULL)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
log_debug("pinode=%d inode=%d nentries=%d nopen=%d is_synced=%d name=%s",
|
log_debug("pinode=%d inode=%d nentries=%d nopen=%d name=%s",
|
||||||
xinode->parent_inode, xinode->inode,
|
xinode->parent_inode, xinode->inode,
|
||||||
xinode->nentries, xinode->nopen, xinode->is_synced,
|
xinode->nentries, xinode->nopen,
|
||||||
xinode->name);
|
xinode->name);
|
||||||
}
|
}
|
||||||
log_debug("%s", "");
|
log_debug("%s", "");
|
||||||
@ -1115,10 +1146,10 @@ static void xfuse_dump_fs(void)
|
|||||||
* @param xino xinode structure to dump
|
* @param xino xinode structure to dump
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
#if 0
|
#ifdef XFUSE_DUMP_ADDED_ENTRIES
|
||||||
static void xfuse_dump_xrdp_inode(struct xrdp_inode *xino)
|
static void xfuse_dump_xrdp_inode(struct xrdp_inode *xino)
|
||||||
{
|
{
|
||||||
log_debug("--- dumping struct xinode ---");
|
log_debug("--- dumping struct xinode %p ---",xino);
|
||||||
log_debug("name: %s", xino->name);
|
log_debug("name: %s", xino->name);
|
||||||
log_debug("parent_inode: %d", xino->parent_inode);
|
log_debug("parent_inode: %d", xino->parent_inode);
|
||||||
log_debug("inode: %d", xino->inode);
|
log_debug("inode: %d", xino->inode);
|
||||||
@ -1193,19 +1224,35 @@ static tui32 xfuse_get_device_id_for_inode(fuse_ino_t ino, char *full_path)
|
|||||||
* @param reverse_path path name in the reverse order
|
* @param reverse_path path name in the reverse order
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
static void fuse_reverse_pathname(char *full_path, char *reverse_path)
|
static void fuse_reverse_pathname(char *full_path, const char *reverse_path)
|
||||||
{
|
{
|
||||||
char *cptr;
|
char *optr; /* Output pointer */
|
||||||
|
const char *start;/* Pointer to start of current element in input */
|
||||||
|
const char *end; /* Ditto for the end */
|
||||||
|
|
||||||
full_path[0] = 0;
|
/* Start writing the result from the end */
|
||||||
|
optr = full_path + strlen(reverse_path);
|
||||||
|
*optr = '\0';
|
||||||
|
|
||||||
while ((cptr = strrchr(reverse_path, '/')) != NULL)
|
start = reverse_path;
|
||||||
|
while ((end = strchr(start, '/')) != NULL)
|
||||||
{
|
{
|
||||||
strcat(full_path, cptr + 1);
|
/* Copy current element to the end of the result... */
|
||||||
strcat(full_path, "/");
|
optr -= (end - start);
|
||||||
cptr[0] = 0;
|
memcpy(optr, start, (end - start));
|
||||||
|
/* And precede with a '/' */
|
||||||
|
*--optr = '/';
|
||||||
|
|
||||||
|
/* Next element starts after the '/' */
|
||||||
|
start = end + 1;
|
||||||
}
|
}
|
||||||
strcat(full_path, reverse_path);
|
|
||||||
|
/* Last bit (if reverse_path doesn't end with a '/') */
|
||||||
|
if (optr != full_path)
|
||||||
|
{
|
||||||
|
memcpy(full_path, start, optr - full_path);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1280,7 +1327,6 @@ xfuse_create_file_in_xrdp_fs(tui32 device_id, int pinode, const char *name,
|
|||||||
xinode->mtime = cur_time;
|
xinode->mtime = cur_time;
|
||||||
xinode->ctime = cur_time;
|
xinode->ctime = cur_time;
|
||||||
xinode->device_id = device_id;
|
xinode->device_id = device_id;
|
||||||
xinode->is_synced = 1;
|
|
||||||
strcpy(xinode->name, name);
|
strcpy(xinode->name, name);
|
||||||
|
|
||||||
if (type == S_IFDIR)
|
if (type == S_IFDIR)
|
||||||
@ -1296,6 +1342,9 @@ xfuse_create_file_in_xrdp_fs(tui32 device_id, int pinode, const char *name,
|
|||||||
|
|
||||||
g_xrdp_fs.inode_table[xinode->inode] = xinode;
|
g_xrdp_fs.inode_table[xinode->inode] = xinode;
|
||||||
g_xrdp_fs.num_entries++;
|
g_xrdp_fs.num_entries++;
|
||||||
|
#ifdef XFUSE_DUMP_ADDED_ENTRIES
|
||||||
|
xfuse_dump_xrdp_inode(xinode);
|
||||||
|
#endif
|
||||||
|
|
||||||
/* 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];
|
||||||
@ -1473,45 +1522,89 @@ static void xfuse_update_xrdpfs_size(void)
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add a file or directory to xrdp file system
|
* Add a file or directory to xrdp file system
|
||||||
|
*
|
||||||
|
* If the file or directory already exists, its attributes are updated.
|
||||||
|
*
|
||||||
|
* Returns a pointer to the xinode if the object was added or updated
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
int xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode)
|
struct xrdp_inode *xfuse_devredir_add_file_or_dir(
|
||||||
|
void *vp,
|
||||||
|
const struct file_attr *fattr)
|
||||||
{
|
{
|
||||||
XFUSE_INFO *fip = (XFUSE_INFO *) vp;
|
XFUSE_INFO *fip = (XFUSE_INFO *) vp;
|
||||||
XRDP_INODE *xip = NULL;
|
XRDP_INODE *xinode = NULL;
|
||||||
|
|
||||||
if ((fip == NULL) || (xinode == NULL))
|
if (fip == NULL)
|
||||||
{
|
{
|
||||||
log_error("fip or xinode are NULL");
|
log_error("fip is NULL");
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
else if (!xfuse_is_inode_valid(fip->inode))
|
||||||
if (!xfuse_is_inode_valid(fip->inode))
|
|
||||||
{
|
{
|
||||||
log_error("inode %ld is not valid", fip->inode);
|
log_error("inode %ld is not valid", fip->inode);
|
||||||
g_free(xinode);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
else if ((strcmp(fattr->name, ".") == 0) ||
|
||||||
log_debug("parent_inode=%ld name=%s", fip->inode, xinode->name);
|
(strcmp(fattr->name, "..") == 0))
|
||||||
|
|
||||||
/* if filename is . or .. don't add it */
|
|
||||||
if ((strcmp(xinode->name, ".") == 0) || (strcmp(xinode->name, "..") == 0))
|
|
||||||
{
|
{
|
||||||
g_free(xinode);
|
; /* filename is . or .. - don't add it */
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_debug("parent_inode=%ld name=%s", fip->inode, fattr->name);
|
||||||
xfuse_dump_fs();
|
xfuse_dump_fs();
|
||||||
|
|
||||||
if ((xip = xfuse_get_inode_from_pinode_name(fip->inode, xinode->name)) != NULL)
|
/* Does the file already exist ? */
|
||||||
|
xinode = xfuse_get_inode_from_pinode_name(fip->inode, fattr->name);
|
||||||
|
if (xinode != NULL)
|
||||||
{
|
{
|
||||||
log_debug("inode=%ld name=%s already exists in xrdp_fs; not adding it",
|
/* Is the existing file the same type ? */
|
||||||
|
if ((xinode->mode & (S_IFREG | S_IFDIR)) ==
|
||||||
|
(fattr->mode & (S_IFREG | S_IFDIR)))
|
||||||
|
{
|
||||||
|
log_debug("inode=%ld name=%s already exists in xrdp_fs"
|
||||||
|
" - updating attributes",
|
||||||
fip->inode, xinode->name);
|
fip->inode, xinode->name);
|
||||||
g_free(xinode);
|
xinode->mode = fattr->mode;
|
||||||
xip->stale = 0;
|
xinode->size = fattr->size;
|
||||||
return -1;
|
xinode->atime = fattr->atime;
|
||||||
|
xinode->mtime = fattr->mtime;
|
||||||
|
xinode->ctime = fattr->ctime;
|
||||||
|
xinode->stale = 0;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* File type has changed */
|
||||||
|
log_debug("inode=%ld name=%s of different type in xrdp_fs"
|
||||||
|
" - removing",
|
||||||
|
fip->inode, xinode->name);
|
||||||
|
if (xinode->mode & S_IFREG)
|
||||||
|
{
|
||||||
|
xfuse_delete_file_with_xinode(xinode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xfuse_delete_dir_with_xinode(xinode);
|
||||||
|
}
|
||||||
|
xinode = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (xinode == NULL)
|
||||||
|
{
|
||||||
|
/* Add a new node to the file system */
|
||||||
|
xinode = g_new0(struct xrdp_inode, 1);
|
||||||
|
if (xinode == NULL)
|
||||||
|
{
|
||||||
|
log_debug("g_new0() failed");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strcpy(xinode->name, fattr->name);
|
||||||
|
xinode->mode = fattr->mode;
|
||||||
|
xinode->size = fattr->size;
|
||||||
|
xinode->atime = fattr->atime;
|
||||||
|
xinode->mtime = fattr->mtime;
|
||||||
|
xinode->ctime = fattr->ctime;
|
||||||
|
|
||||||
xinode->parent_inode = fip->inode;
|
xinode->parent_inode = fip->inode;
|
||||||
xinode->inode = g_xrdp_fs.next_node++;
|
xinode->inode = g_xrdp_fs.next_node++;
|
||||||
@ -1527,10 +1620,18 @@ int xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode)
|
|||||||
xfuse_update_xrdpfs_size();
|
xfuse_update_xrdpfs_size();
|
||||||
|
|
||||||
xfuse_dump_fs();
|
xfuse_dump_fs();
|
||||||
return 0;
|
#ifdef XFUSE_DUMP_ADDED_ENTRIES
|
||||||
|
xfuse_dump_xrdp_inode(xinode);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return xinode;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* This routine is called by devredir when the opendir_req entry at the
|
||||||
|
* front of the opendir FIFO has completed processing.
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus)
|
void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus)
|
||||||
@ -1551,7 +1652,6 @@ void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus)
|
|||||||
if (IoStatus != 0)
|
if (IoStatus != 0)
|
||||||
{
|
{
|
||||||
/* command failed */
|
/* command failed */
|
||||||
if (fip->invoke_fuse)
|
|
||||||
fuse_reply_err(fip->req, ENOENT);
|
fuse_reply_err(fip->req, ENOENT);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
@ -1560,14 +1660,15 @@ void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus)
|
|||||||
if (!xfuse_is_inode_valid(fip->inode))
|
if (!xfuse_is_inode_valid(fip->inode))
|
||||||
{
|
{
|
||||||
log_error("inode %ld is not valid", fip->inode);
|
log_error("inode %ld is not valid", fip->inode);
|
||||||
if (fip->invoke_fuse)
|
|
||||||
fuse_reply_err(fip->req, EBADF);
|
fuse_reply_err(fip->req, EBADF);
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
xfuse_delete_stale_entries(fip->inode);
|
xfuse_delete_stale_entries(fip->inode);
|
||||||
|
|
||||||
/* this will be used by xfuse_cb_readdir() */
|
/* Generate a FUSE reply.
|
||||||
|
* The dir_info struct will be used by xfuse_cb_readdir()
|
||||||
|
*/
|
||||||
di = g_new0(struct dir_info, 1);
|
di = g_new0(struct dir_info, 1);
|
||||||
di->index = FIRST_INODE;
|
di->index = FIRST_INODE;
|
||||||
fip->fi->fh = (tintptr) di;
|
fip->fi->fh = (tintptr) di;
|
||||||
@ -1576,10 +1677,9 @@ void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus)
|
|||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
if (fip)
|
|
||||||
free(fip);
|
free(fip);
|
||||||
|
|
||||||
/* remove current request */
|
/* remove completed request */
|
||||||
g_free(fifo_remove(&g_fifo_opendir));
|
g_free(fifo_remove(&g_fifo_opendir));
|
||||||
|
|
||||||
while (1)
|
while (1)
|
||||||
@ -1596,6 +1696,44 @@ done:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This routine is caused as a result of a devredir remote lookup
|
||||||
|
* instigated by xfuse_cb_lookup()
|
||||||
|
*
|
||||||
|
* If the IoStatus is good but there's no xinode, something has gone wrong
|
||||||
|
* in the devredir layer (no memory, unrecognised reply)
|
||||||
|
*****************************************************************************/
|
||||||
|
void xfuse_devredir_cb_lookup_entry(void *vp, tui32 IoStatus, struct xrdp_inode *xinode)
|
||||||
|
{
|
||||||
|
XFUSE_INFO *fip = (XFUSE_INFO *) vp;
|
||||||
|
|
||||||
|
if (IoStatus == NT_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
if (xinode != NULL)
|
||||||
|
{
|
||||||
|
make_fuse_entry_reply(fip->req, xinode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fuse_reply_err(fip->req, EIO);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
switch (IoStatus)
|
||||||
|
{
|
||||||
|
case NT_STATUS_NO_SUCH_FILE:
|
||||||
|
fuse_reply_err(fip->req, ENOENT);
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log_info("Error code %08x - fallthrough", (int) IoStatus);
|
||||||
|
fuse_reply_err(fip->req, EIO);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId,
|
void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId,
|
||||||
tui32 FileId)
|
tui32 FileId)
|
||||||
{
|
{
|
||||||
@ -1614,17 +1752,14 @@ void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId,
|
|||||||
|
|
||||||
if (IoStatus != 0)
|
if (IoStatus != 0)
|
||||||
{
|
{
|
||||||
if (!fip->invoke_fuse)
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
switch (IoStatus)
|
switch (IoStatus)
|
||||||
{
|
{
|
||||||
case 0xC0000022:
|
case NT_STATUS_ACCESS_DENIED:
|
||||||
fuse_reply_err(fip->req, EACCES);
|
fuse_reply_err(fip->req, EACCES);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 0xC0000033:
|
case NT_STATUS_OBJECT_NAME_INVALID:
|
||||||
case 0xC0000034:
|
case NT_STATUS_OBJECT_NAME_NOT_FOUND:
|
||||||
fuse_reply_err(fip->req, ENOENT);
|
fuse_reply_err(fip->req, ENOENT);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -1642,7 +1777,6 @@ void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId,
|
|||||||
if (fh == NULL)
|
if (fh == NULL)
|
||||||
{
|
{
|
||||||
log_error("system out of memory");
|
log_error("system out of memory");
|
||||||
if (fip->invoke_fuse)
|
|
||||||
fuse_reply_err(fip->req, ENOMEM);
|
fuse_reply_err(fip->req, ENOMEM);
|
||||||
|
|
||||||
free(fip);
|
free(fip);
|
||||||
@ -1658,8 +1792,6 @@ void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId,
|
|||||||
fip, fip->fi, (long long) fip->fi->fh);
|
fip, fip->fi, (long long) fip->fi->fh);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fip->invoke_fuse)
|
|
||||||
{
|
|
||||||
if (fip->reply_type == RT_FUSE_REPLY_OPEN)
|
if (fip->reply_type == RT_FUSE_REPLY_OPEN)
|
||||||
{
|
{
|
||||||
log_debug("sending fuse_reply_open(); "
|
log_debug("sending fuse_reply_open(); "
|
||||||
@ -1724,7 +1856,6 @@ void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId,
|
|||||||
{
|
{
|
||||||
log_error("invalid reply type: %d", fip->reply_type);
|
log_error("invalid reply type: %d", fip->reply_type);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
done:
|
||||||
|
|
||||||
@ -1746,7 +1877,10 @@ void xfuse_devredir_cb_read_file(void *vp, const char *buf, size_t length)
|
|||||||
free(fip);
|
free(fip);
|
||||||
}
|
}
|
||||||
|
|
||||||
void xfuse_devredir_cb_write_file(void *vp, const char *buf, size_t length)
|
void xfuse_devredir_cb_write_file(void *vp,
|
||||||
|
tui32 IoStatus,
|
||||||
|
const char *buf,
|
||||||
|
size_t length)
|
||||||
{
|
{
|
||||||
XRDP_INODE *xinode;
|
XRDP_INODE *xinode;
|
||||||
XFUSE_INFO *fip;
|
XFUSE_INFO *fip;
|
||||||
@ -1755,20 +1889,36 @@ void xfuse_devredir_cb_write_file(void *vp, const char *buf, size_t length)
|
|||||||
if ((fip == NULL) || (fip->req == NULL) || (fip->fi == NULL))
|
if ((fip == NULL) || (fip->req == NULL) || (fip->fi == NULL))
|
||||||
{
|
{
|
||||||
log_error("fip, fip->req or fip->fi is NULL");
|
log_error("fip, fip->req or fip->fi is NULL");
|
||||||
return;
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
log_debug("+++ XFUSE_INFO=%p, XFUSE_INFO->fi=%p XFUSE_INFO->fi->fh=0x%llx",
|
{
|
||||||
|
log_debug(
|
||||||
|
"+++ XFUSE_INFO=%p, XFUSE_INFO->fi=%p XFUSE_INFO->fi->fh=0x%llx",
|
||||||
fip, fip->fi, (long long) fip->fi->fh);
|
fip, fip->fi, (long long) fip->fi->fh);
|
||||||
|
|
||||||
|
if (IoStatus != NT_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
log_error("Write NTSTATUS is %d", (int) IoStatus);
|
||||||
|
fuse_reply_err(fip->req, EIO);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
fuse_reply_write(fip->req, length);
|
fuse_reply_write(fip->req, length);
|
||||||
|
|
||||||
/* update file size */
|
/* update file size */
|
||||||
|
/* ??? This needs to take into account the offset sent with
|
||||||
|
* the original request */
|
||||||
if ((xinode = g_xrdp_fs.inode_table[fip->inode]) != NULL)
|
if ((xinode = g_xrdp_fs.inode_table[fip->inode]) != NULL)
|
||||||
|
{
|
||||||
xinode->size += length;
|
xinode->size += length;
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
log_error("inode at inode_table[%ld] is NULL", fip->inode);
|
log_error("inode at inode_table[%ld] is NULL", fip->inode);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
free(fip);
|
free(fip);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1861,7 +2011,6 @@ void xfuse_devredir_cb_rename_file(void *vp, tui32 IoStatus)
|
|||||||
if (fip->inode != fip->new_inode)
|
if (fip->inode != fip->new_inode)
|
||||||
{
|
{
|
||||||
/* file has been moved to a different dir */
|
/* file has been moved to a different dir */
|
||||||
old_xinode->is_synced = 1;
|
|
||||||
g_xrdp_fs.inode_table[fip->inode]->nentries--;
|
g_xrdp_fs.inode_table[fip->inode]->nentries--;
|
||||||
g_xrdp_fs.inode_table[fip->new_inode]->nentries++;
|
g_xrdp_fs.inode_table[fip->new_inode]->nentries++;
|
||||||
}
|
}
|
||||||
@ -1927,12 +2076,20 @@ void xfuse_devredir_cb_file_close(void *vp)
|
|||||||
/**
|
/**
|
||||||
* Look up a directory entry by name and get its attributes
|
* Look up a directory entry by name and get its attributes
|
||||||
*
|
*
|
||||||
|
* If the file can't be found, and it resides on a remote share, devredir
|
||||||
|
* is asked to look it up. This will result in the following
|
||||||
|
* callbacks:-
|
||||||
|
* - xfuse_devredir_add_file_or_dir() (only if the file is found)
|
||||||
|
* - xfuse_devredir_cb_lookup_entry() to return status to the caller
|
||||||
*****************************************************************************/
|
*****************************************************************************/
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
|
XFUSE_INFO *fip;
|
||||||
XRDP_INODE *xinode;
|
XRDP_INODE *xinode;
|
||||||
struct fuse_entry_param e;
|
char full_path[4096];
|
||||||
|
tui32 device_id;
|
||||||
|
const char *cptr;
|
||||||
|
|
||||||
log_debug("looking for parent=%ld name=%s", parent, name);
|
log_debug("looking for parent=%ld name=%s", parent, name);
|
||||||
xfuse_dump_fs();
|
xfuse_dump_fs();
|
||||||
@ -1944,33 +2101,60 @@ static void xfuse_cb_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
xinode = xfuse_get_inode_from_pinode_name(parent, name);
|
if (parent == 1 ||
|
||||||
if (xinode == NULL)
|
g_xrdp_fs.inode_table[parent]->is_loc_resource)
|
||||||
|
{
|
||||||
|
/* File cannot be remote - we either know about it or we don't */
|
||||||
|
xinode = xfuse_get_inode_from_pinode_name(parent, name);
|
||||||
|
if (xinode != NULL)
|
||||||
{
|
{
|
||||||
log_debug("did not find entry for parent=%ld 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=%ld name=%s uid=%d gid=%d",
|
log_debug("found entry for parent=%ld name=%s uid=%d gid=%d",
|
||||||
parent, name, xinode->uid, xinode->gid);
|
parent, name, xinode->uid, xinode->gid);
|
||||||
return;
|
make_fuse_entry_reply(req, xinode);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
fuse_reply_err(req, ENOENT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* specified file resides on redirected share.
|
||||||
|
*
|
||||||
|
* We always look these up, as fuse caches stuff for us anyway, and
|
||||||
|
* it's pointless caching it twice
|
||||||
|
*/
|
||||||
|
fip = g_new0(XFUSE_INFO, 1);
|
||||||
|
if (fip == NULL)
|
||||||
|
{
|
||||||
|
log_error("system out of memory");
|
||||||
|
fuse_reply_err(req, ENOMEM);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
device_id = xfuse_get_device_id_for_inode(parent, full_path);
|
||||||
|
|
||||||
|
/* we want path minus 'root node of the share' */
|
||||||
|
if ((cptr = strchr(full_path, '/')) == NULL)
|
||||||
|
{
|
||||||
|
cptr = "\\";
|
||||||
|
}
|
||||||
|
|
||||||
|
fip->req = req;
|
||||||
|
fip->inode = parent;
|
||||||
|
fip->device_id = device_id;
|
||||||
|
|
||||||
|
log_debug("Looking up %s in %s on %d", name, cptr, device_id);
|
||||||
|
if (dev_redir_lookup_entry((void *) fip, device_id,
|
||||||
|
cptr, name))
|
||||||
|
{
|
||||||
|
log_error("failed to send dev_redir_lookup_entry() cmd");
|
||||||
|
fuse_reply_err(req, EREMOTEIO);
|
||||||
|
free(fip);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2106,8 +2290,6 @@ static void xfuse_cb_readdir(fuse_req_t req, fuse_ino_t ino, size_t size,
|
|||||||
if (xinode->parent_inode != ino)
|
if (xinode->parent_inode != ino)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
xinode->is_synced = 1;
|
|
||||||
|
|
||||||
if (first_time)
|
if (first_time)
|
||||||
{
|
{
|
||||||
first_time = 0;
|
first_time = 0;
|
||||||
@ -2198,7 +2380,7 @@ static void xfuse_remove_dir_or_file(fuse_req_t req, fuse_ino_t parent,
|
|||||||
{
|
{
|
||||||
XFUSE_INFO *fip;
|
XFUSE_INFO *fip;
|
||||||
XRDP_INODE *xinode;
|
XRDP_INODE *xinode;
|
||||||
char *cptr;
|
const char *cptr;
|
||||||
char full_path[4096];
|
char full_path[4096];
|
||||||
tui32 device_id;
|
tui32 device_id;
|
||||||
|
|
||||||
@ -2265,7 +2447,6 @@ static void xfuse_remove_dir_or_file(fuse_req_t req, fuse_ino_t parent,
|
|||||||
|
|
||||||
fip->req = req;
|
fip->req = req;
|
||||||
fip->inode = parent;
|
fip->inode = parent;
|
||||||
fip->invoke_fuse = 1;
|
|
||||||
fip->device_id = device_id;
|
fip->device_id = device_id;
|
||||||
strncpy(fip->name, name, 1024);
|
strncpy(fip->name, name, 1024);
|
||||||
fip->name[1023] = 0;
|
fip->name[1023] = 0;
|
||||||
@ -2274,24 +2455,15 @@ static void xfuse_remove_dir_or_file(fuse_req_t req, fuse_ino_t parent,
|
|||||||
/* 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)
|
||||||
{
|
{
|
||||||
|
cptr = "\\";
|
||||||
|
}
|
||||||
|
|
||||||
/* get dev_redir to open the remote file */
|
/* get dev_redir to open the remote file */
|
||||||
if (devredir_rmdir_or_file((void *) fip, device_id, "\\", O_RDWR))
|
|
||||||
{
|
|
||||||
log_error("failed to send dev_redir_open_file() cmd");
|
|
||||||
fuse_reply_err(req, EREMOTEIO);
|
|
||||||
free(fip);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (devredir_rmdir_or_file((void *) fip, device_id, cptr, O_RDWR))
|
if (devredir_rmdir_or_file((void *) fip, device_id, cptr, O_RDWR))
|
||||||
{
|
{
|
||||||
log_error("failed to send dev_redir_get_dir_listing() cmd");
|
log_error("failed to send devredir_rmdir_or_file() cmd");
|
||||||
fuse_reply_err(req, EREMOTEIO);
|
fuse_reply_err(req, EREMOTEIO);
|
||||||
free(fip);
|
free(fip);
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2302,7 +2474,7 @@ static void xfuse_cb_rename(fuse_req_t req,
|
|||||||
XRDP_INODE *old_xinode;
|
XRDP_INODE *old_xinode;
|
||||||
XFUSE_INFO *fip;
|
XFUSE_INFO *fip;
|
||||||
tui32 new_device_id;
|
tui32 new_device_id;
|
||||||
char *cptr;
|
const char *cptr;
|
||||||
char old_full_path[1024];
|
char old_full_path[1024];
|
||||||
char new_full_path[1024];
|
char new_full_path[1024];
|
||||||
const char *cp;
|
const char *cp;
|
||||||
@ -2400,35 +2572,26 @@ static void xfuse_cb_rename(fuse_req_t req,
|
|||||||
strncpy(fip->new_name, new_name, 1024);
|
strncpy(fip->new_name, new_name, 1024);
|
||||||
fip->name[1023] = 0;
|
fip->name[1023] = 0;
|
||||||
fip->new_name[1023] = 0;
|
fip->new_name[1023] = 0;
|
||||||
fip->invoke_fuse = 1;
|
|
||||||
fip->device_id = device_id;
|
fip->device_id = device_id;
|
||||||
|
|
||||||
if ((cp = strchr(new_full_path, '/')) == NULL)
|
|
||||||
cp = "\\";
|
|
||||||
|
|
||||||
/* we want path minus 'root node of the share' */
|
/* we want path minus 'root node of the share' */
|
||||||
if ((cptr = strchr(old_full_path, '/')) == NULL)
|
if ((cptr = strchr(old_full_path, '/')) == NULL)
|
||||||
{
|
{
|
||||||
|
cptr = "\\";
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((cp = strchr(new_full_path, '/')) == NULL)
|
||||||
|
{
|
||||||
|
cp = "\\";
|
||||||
|
}
|
||||||
|
|
||||||
/* 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, "\\",
|
|
||||||
O_RDWR, S_IFREG | OP_RENAME_FILE, cp))
|
|
||||||
{
|
|
||||||
log_error("failed to send dev_redir_file_open() cmd");
|
|
||||||
fuse_reply_err(req, EREMOTEIO);
|
|
||||||
free(fip);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (dev_redir_file_open((void *) fip, device_id, cptr,
|
if (dev_redir_file_open((void *) fip, device_id, cptr,
|
||||||
O_RDWR, S_IFREG | OP_RENAME_FILE, cp))
|
O_RDWR, S_IFREG | OP_RENAME_FILE, cp))
|
||||||
{
|
{
|
||||||
log_error("failed to send dev_redir_file_open() cmd");
|
log_error("failed to send dev_redir_file_open() cmd");
|
||||||
fuse_reply_err(req, EREMOTEIO);
|
fuse_reply_err(req, EREMOTEIO);
|
||||||
free(fip);
|
free(fip);
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2448,7 +2611,7 @@ static void xfuse_create_dir_or_file(fuse_req_t req, fuse_ino_t parent,
|
|||||||
struct fuse_file_info *fi, int type)
|
struct fuse_file_info *fi, int type)
|
||||||
{
|
{
|
||||||
XFUSE_INFO *fip;
|
XFUSE_INFO *fip;
|
||||||
char *cptr;
|
const char *cptr;
|
||||||
char full_path[1024];
|
char full_path[1024];
|
||||||
tui32 device_id;
|
tui32 device_id;
|
||||||
|
|
||||||
@ -2501,7 +2664,6 @@ static void xfuse_create_dir_or_file(fuse_req_t req, fuse_ino_t parent,
|
|||||||
fip->req = req;
|
fip->req = req;
|
||||||
fip->fi = fi;
|
fip->fi = fi;
|
||||||
fip->inode = parent;
|
fip->inode = parent;
|
||||||
fip->invoke_fuse = 1;
|
|
||||||
fip->device_id = device_id;
|
fip->device_id = device_id;
|
||||||
fip->mode = type;
|
fip->mode = type;
|
||||||
fip->reply_type = RT_FUSE_REPLY_CREATE;
|
fip->reply_type = RT_FUSE_REPLY_CREATE;
|
||||||
@ -2515,23 +2677,16 @@ static void xfuse_create_dir_or_file(fuse_req_t req, fuse_ino_t parent,
|
|||||||
/* 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)
|
||||||
{
|
{
|
||||||
|
cptr = "\\";
|
||||||
|
}
|
||||||
|
|
||||||
/* 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, "\\",
|
|
||||||
O_CREAT, type, NULL))
|
|
||||||
{
|
|
||||||
log_error("failed to send dev_redir_open_file() cmd");
|
|
||||||
fuse_reply_err(req, EREMOTEIO);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (dev_redir_file_open((void *) fip, device_id, cptr,
|
if (dev_redir_file_open((void *) fip, device_id, cptr,
|
||||||
O_CREAT, type, NULL))
|
O_CREAT, type, NULL))
|
||||||
{
|
{
|
||||||
log_error("failed to send dev_redir_get_dir_listing() cmd");
|
log_error("failed to send dev_redir_file_open() cmd");
|
||||||
fuse_reply_err(req, EREMOTEIO);
|
fuse_reply_err(req, EREMOTEIO);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -2543,7 +2698,7 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
|
|||||||
{
|
{
|
||||||
XRDP_INODE *xinode;
|
XRDP_INODE *xinode;
|
||||||
XFUSE_INFO *fip;
|
XFUSE_INFO *fip;
|
||||||
char *cptr;
|
const char *cptr;
|
||||||
char full_path[4096];
|
char full_path[4096];
|
||||||
tui32 device_id;
|
tui32 device_id;
|
||||||
|
|
||||||
@ -2566,11 +2721,24 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
|
|||||||
}
|
}
|
||||||
if (xinode->mode & S_IFDIR)
|
if (xinode->mode & S_IFDIR)
|
||||||
{
|
{
|
||||||
log_debug("reading a dir not allowed!");
|
log_debug("reading/writing a dir not allowed!");
|
||||||
fuse_reply_err(req, EISDIR);
|
fuse_reply_err(req, EISDIR);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
switch (fi->flags & O_ACCMODE)
|
||||||
|
{
|
||||||
|
case O_RDONLY:
|
||||||
|
case O_WRONLY:
|
||||||
|
case O_RDWR:
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
log_debug("Invalid access mode specified");
|
||||||
|
fuse_reply_err(req, EINVAL);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
device_id = xfuse_get_device_id_for_inode(ino, full_path);
|
device_id = xfuse_get_device_id_for_inode(ino, full_path);
|
||||||
|
|
||||||
if (xinode->is_loc_resource)
|
if (xinode->is_loc_resource)
|
||||||
@ -2595,7 +2763,6 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
|
|||||||
|
|
||||||
fip->req = req;
|
fip->req = req;
|
||||||
fip->inode = ino;
|
fip->inode = ino;
|
||||||
fip->invoke_fuse = 1;
|
|
||||||
fip->device_id = device_id;
|
fip->device_id = device_id;
|
||||||
fip->fi = fi;
|
fip->fi = fi;
|
||||||
|
|
||||||
@ -2608,23 +2775,20 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
|
|||||||
/* 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 */
|
cptr = "\\";
|
||||||
if (dev_redir_file_open((void *) fip, device_id, "\\",
|
|
||||||
fi->flags, S_IFREG, NULL))
|
|
||||||
{
|
|
||||||
log_error("failed to send dev_redir_open_file() cmd");
|
|
||||||
fuse_reply_err(req, EREMOTEIO);
|
|
||||||
}
|
}
|
||||||
}
|
/* get dev_redir to open the remote file
|
||||||
else
|
*
|
||||||
{
|
* For a successful call, if the caller has set O_TRUNC when writing
|
||||||
|
* the file, fuse should call us back via fuse_cb_setattr() to set
|
||||||
|
* the size to zero - we don't need to do this ourselves.
|
||||||
|
*/
|
||||||
if (dev_redir_file_open((void *) fip, device_id, cptr,
|
if (dev_redir_file_open((void *) fip, device_id, cptr,
|
||||||
fi->flags, S_IFREG, NULL))
|
fi->flags, S_IFREG, NULL))
|
||||||
{
|
{
|
||||||
log_error("failed to send dev_redir_get_dir_listing() cmd");
|
log_error("failed to send dev_redir_file_open() cmd");
|
||||||
fuse_reply_err(req, EREMOTEIO);
|
fuse_reply_err(req, EREMOTEIO);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void xfuse_cb_release(fuse_req_t req, fuse_ino_t ino, struct
|
static void xfuse_cb_release(fuse_req_t req, fuse_ino_t ino, struct
|
||||||
@ -2679,7 +2843,6 @@ static void xfuse_cb_release(fuse_req_t req, fuse_ino_t ino, struct
|
|||||||
|
|
||||||
fip->req = req;
|
fip->req = req;
|
||||||
fip->inode = ino;
|
fip->inode = ino;
|
||||||
fip->invoke_fuse = 1;
|
|
||||||
fip->device_id = handle->DeviceId;
|
fip->device_id = handle->DeviceId;
|
||||||
fip->fi = fi;
|
fip->fi = fi;
|
||||||
|
|
||||||
@ -2766,7 +2929,6 @@ static void xfuse_cb_read(fuse_req_t req, fuse_ino_t ino, size_t size,
|
|||||||
}
|
}
|
||||||
fusep->req = req;
|
fusep->req = req;
|
||||||
fusep->inode = ino;
|
fusep->inode = ino;
|
||||||
fusep->invoke_fuse = 1;
|
|
||||||
fusep->device_id = fh->DeviceId;
|
fusep->device_id = fh->DeviceId;
|
||||||
fusep->fi = fi;
|
fusep->fi = fi;
|
||||||
|
|
||||||
@ -2815,7 +2977,6 @@ static void xfuse_cb_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
|
|||||||
|
|
||||||
fusep->req = req;
|
fusep->req = req;
|
||||||
fusep->inode = ino;
|
fusep->inode = ino;
|
||||||
fusep->invoke_fuse = 1;
|
|
||||||
fusep->device_id = fh->DeviceId;
|
fusep->device_id = fh->DeviceId;
|
||||||
fusep->fi = fi;
|
fusep->fi = fi;
|
||||||
|
|
||||||
@ -2979,7 +3140,7 @@ static int xfuse_proc_opendir_req(fuse_req_t req, fuse_ino_t ino,
|
|||||||
XFUSE_INFO *fip;
|
XFUSE_INFO *fip;
|
||||||
tui32 device_id;
|
tui32 device_id;
|
||||||
char full_path[4096];
|
char full_path[4096];
|
||||||
char *cptr;
|
const char *cptr;
|
||||||
|
|
||||||
log_debug("inode=%ld", ino);
|
log_debug("inode=%ld", ino);
|
||||||
|
|
||||||
@ -3006,22 +3167,6 @@ static int xfuse_proc_opendir_req(fuse_req_t req, fuse_ino_t ino,
|
|||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* enumerate resources on a remote device */
|
/* enumerate resources on a remote device */
|
||||||
|
|
||||||
#ifdef USE_SYNC_FLAG
|
|
||||||
if (xinode->is_synced)
|
|
||||||
{
|
|
||||||
xfuse_enum_dir(req, ino, size, off, fi);
|
|
||||||
g_free(fifo_remove(&g_fifo_opendir));
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
goto do_remote_lookup;
|
|
||||||
}
|
|
||||||
|
|
||||||
do_remote_lookup:
|
|
||||||
#endif
|
|
||||||
|
|
||||||
xfuse_mark_as_stale(ino);
|
xfuse_mark_as_stale(ino);
|
||||||
|
|
||||||
log_debug("did not find entry; redirecting call to dev_redir");
|
log_debug("did not find entry; redirecting call to dev_redir");
|
||||||
@ -3041,32 +3186,21 @@ do_remote_lookup:
|
|||||||
fip->req = req;
|
fip->req = req;
|
||||||
fip->inode = ino;
|
fip->inode = ino;
|
||||||
fip->size = 0;
|
fip->size = 0;
|
||||||
fip->off = 0;
|
|
||||||
fip->fi = fi;
|
fip->fi = fi;
|
||||||
fip->dirbuf1.first_time = 1;
|
|
||||||
fip->dirbuf1.bytes_in_buf = 0;
|
|
||||||
|
|
||||||
fip->invoke_fuse = 1;
|
|
||||||
fip->device_id = device_id;
|
fip->device_id = device_id;
|
||||||
|
|
||||||
/* 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)
|
||||||
{
|
{
|
||||||
/* enumerate root dir */
|
cptr = "\\";
|
||||||
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))
|
if (dev_redir_get_dir_listing((void *) fip, device_id, cptr))
|
||||||
{
|
{
|
||||||
log_error("failed to send dev_redir_get_dir_listing() cmd");
|
log_error("failed to send dev_redir_get_dir_listing() cmd");
|
||||||
fuse_reply_buf(req, NULL, 0);
|
fuse_reply_buf(req, NULL, 0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@ -3164,4 +3298,26 @@ xfuse_delete_stale_entries(fuse_ino_t pinode)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void make_fuse_entry_reply(fuse_req_t req, const XRDP_INODE *xinode)
|
||||||
|
{
|
||||||
|
struct fuse_entry_param e;
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
#endif /* end else #ifndef XRDP_FUSE */
|
#endif /* end else #ifndef XRDP_FUSE */
|
||||||
|
@ -19,31 +19,27 @@
|
|||||||
#ifndef _CHANSRV_FUSE_H
|
#ifndef _CHANSRV_FUSE_H
|
||||||
#define _CHANSRV_FUSE_H
|
#define _CHANSRV_FUSE_H
|
||||||
|
|
||||||
/* a file or dir entry in the xrdp file system */
|
#include "arch.h"
|
||||||
struct xrdp_inode
|
|
||||||
|
/*
|
||||||
|
* a file or dir entry in the xrdp file system (opaque type externally) */
|
||||||
|
struct xrdp_inode;
|
||||||
|
|
||||||
|
/* Used to pass file info in to xfuse_devredir_add_file_or_dir()
|
||||||
|
*
|
||||||
|
* The string storage the name field points to is only valid
|
||||||
|
* for the duration of the xfuse_devredir_add_file_or_dir()
|
||||||
|
* call
|
||||||
|
*/
|
||||||
|
struct file_attr
|
||||||
{
|
{
|
||||||
tui32 parent_inode; /* Parent serial number. */
|
const char *name; /* Name of file or directory */
|
||||||
tui32 inode; /* File serial number. */
|
|
||||||
tui32 mode; /* File mode. */
|
tui32 mode; /* File mode. */
|
||||||
tui32 nlink; /* symbolic link count. */
|
|
||||||
tui32 nentries; /* number of entries in a dir */
|
|
||||||
tui32 nopen; /* number of simultaneous opens */
|
|
||||||
tui32 uid; /* User ID of the file's owner. */
|
|
||||||
tui32 gid; /* Group ID of the file's group. */
|
|
||||||
size_t size; /* Size of file, in bytes. */
|
size_t size; /* Size of file, in bytes. */
|
||||||
time_t atime; /* Time of last access. */
|
time_t atime; /* Time of last access. */
|
||||||
time_t mtime; /* Time of last modification. */
|
time_t mtime; /* Time of last modification. */
|
||||||
time_t ctime; /* Time of last status change. */
|
time_t ctime; /* Time of last status change. */
|
||||||
char name[1024]; /* Dir or filename */
|
|
||||||
tui32 device_id; /* for file system redirection */
|
|
||||||
char is_synced; /* dir struct has been read from */
|
|
||||||
/* remote device, done just once */
|
|
||||||
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
|
|
||||||
|
|
||||||
int xfuse_init(void);
|
int xfuse_init(void);
|
||||||
int xfuse_deinit(void);
|
int xfuse_deinit(void);
|
||||||
@ -57,9 +53,18 @@ int xfuse_file_contents_size(int stream_id, int file_size);
|
|||||||
int xfuse_add_clip_dir_item(const char *filename, int flags, int size, int lindex);
|
int xfuse_add_clip_dir_item(const char *filename, int flags, int size, int lindex);
|
||||||
|
|
||||||
/* functions that are invoked from devredir */
|
/* functions that are invoked from devredir */
|
||||||
int xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode);
|
struct xrdp_inode *xfuse_devredir_add_file_or_dir(
|
||||||
|
void *vp,
|
||||||
|
const struct file_attr *file_info);
|
||||||
void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus);
|
void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus);
|
||||||
|
void xfuse_devredir_cb_lookup_entry(void *vp, tui32 IoStatus,
|
||||||
|
struct xrdp_inode *xinode);
|
||||||
void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId, tui32 FileId);
|
void xfuse_devredir_cb_open_file(void *vp, tui32 IoStatus, tui32 DeviceId, tui32 FileId);
|
||||||
|
void xfuse_devredir_cb_write_file(
|
||||||
|
void *vp,
|
||||||
|
tui32 IoStatus,
|
||||||
|
const char *buf,
|
||||||
|
size_t length);
|
||||||
void xfuse_devredir_cb_read_file(void *vp, const char *buf, size_t length);
|
void xfuse_devredir_cb_read_file(void *vp, const char *buf, size_t length);
|
||||||
void xfuse_devredir_cb_rmdir_or_file(void *vp, tui32 IoStatus);
|
void xfuse_devredir_cb_rmdir_or_file(void *vp, tui32 IoStatus);
|
||||||
void xfuse_devredir_cb_rename_file(void *vp, tui32 IoStatus);
|
void xfuse_devredir_cb_rename_file(void *vp, tui32 IoStatus);
|
||||||
|
@ -91,6 +91,13 @@
|
|||||||
} \
|
} \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Size of structs supported by IRP_MJ_QUERY_INFORMATION without
|
||||||
|
* trailing RESERVED fields (MS-RDPEFS 2.2.3.3.8)
|
||||||
|
*/
|
||||||
|
#define FILE_BASIC_INFORMATION_SIZE 36
|
||||||
|
#define FILE_STD_INFORMATION_SIZE 22
|
||||||
|
|
||||||
/* globals */
|
/* globals */
|
||||||
extern int g_rdpdr_chan_id; /* in chansrv.c */
|
extern int g_rdpdr_chan_id; /* in chansrv.c */
|
||||||
int g_is_printer_redir_supported = 0;
|
int g_is_printer_redir_supported = 0;
|
||||||
@ -106,7 +113,26 @@ tui32 g_device_id; /* unique device ID - announced by client */
|
|||||||
tui16 g_client_rdp_version; /* returned by client */
|
tui16 g_client_rdp_version; /* returned by client */
|
||||||
struct stream *g_input_stream = NULL;
|
struct stream *g_input_stream = NULL;
|
||||||
|
|
||||||
void xfuse_devredir_cb_write_file(void *vp, const char *buf, size_t length);
|
/*
|
||||||
|
* Local functions called from dev_redir_proc_device_iocompletion()
|
||||||
|
*/
|
||||||
|
static void devredir_proc_cid_rmdir_or_file(IRP *irp, tui32 IoStatus);
|
||||||
|
static void devredir_proc_cid_rmdir_or_file_resp(IRP *irp, tui32 IoStatus);
|
||||||
|
static void devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus);
|
||||||
|
static void devredir_proc_cid_rename_file_resp(IRP *irp, tui32 IoStatus);
|
||||||
|
static void devredir_proc_cid_lookup_basic_entry(IRP *irp, tui32 IoStatus);
|
||||||
|
static void devredir_proc_cid_lookup_basic_entry_resp(
|
||||||
|
IRP *irp,
|
||||||
|
struct stream *s_in,
|
||||||
|
tui32 IoStatus);
|
||||||
|
static void devredir_proc_cid_lookup_std_entry_resp(
|
||||||
|
IRP *irp,
|
||||||
|
struct stream *s_in,
|
||||||
|
tui32 DeviceId,
|
||||||
|
tui32 CompletionId,
|
||||||
|
tui32 IoStatus);
|
||||||
|
/* Other local functions */
|
||||||
|
static void lookup_std_entry(IRP *irp);
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
int
|
int
|
||||||
@ -816,7 +842,8 @@ dev_redir_proc_device_iocompletion(struct stream *s)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
xfuse_devredir_cb_write_file(fuse_data->data_ptr, s->p, Length);
|
xfuse_devredir_cb_write_file(fuse_data->data_ptr, IoStatus,
|
||||||
|
s->p, Length);
|
||||||
devredir_irp_delete(irp);
|
devredir_irp_delete(irp);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
@ -866,6 +893,27 @@ dev_redir_proc_device_iocompletion(struct stream *s)
|
|||||||
devredir_proc_cid_rename_file_resp(irp, IoStatus);
|
devredir_proc_cid_rename_file_resp(irp, IoStatus);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case CID_LOOKUP_BASIC_ENTRY:
|
||||||
|
log_debug("got CID_LOOKUP_BASIC_ENTRY");
|
||||||
|
xstream_rd_u32_le(s, irp->FileId);
|
||||||
|
/* Issue a call to get the FileBasicInformation */
|
||||||
|
devredir_proc_cid_lookup_basic_entry(irp, IoStatus);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CID_LOOKUP_STD_ENTRY:
|
||||||
|
log_debug("got CID_LOOKUP_STD_ENTRY");
|
||||||
|
/* Parse the FileBasicInformation and request the
|
||||||
|
* FileStandardInformation */
|
||||||
|
devredir_proc_cid_lookup_basic_entry_resp(irp, s, IoStatus);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CID_LOOKUP_ENTRY_RESP:
|
||||||
|
/* Parse the FileStandardInformation and respond to caller */
|
||||||
|
log_debug("got CID_LOOKUP_ENTRY_RESP");
|
||||||
|
devredir_proc_cid_lookup_std_entry_resp(irp, s, DeviceId,
|
||||||
|
CompletionId, IoStatus);
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log_error("got unknown CompletionID: DeviceId=0x%x "
|
log_error("got unknown CompletionID: DeviceId=0x%x "
|
||||||
"CompletionId=0x%x IoStatus=0x%x",
|
"CompletionId=0x%x IoStatus=0x%x",
|
||||||
@ -892,7 +940,6 @@ dev_redir_proc_query_dir_response(IRP *irp,
|
|||||||
tui32 IoStatus)
|
tui32 IoStatus)
|
||||||
{
|
{
|
||||||
FUSE_DATA *fuse_data = NULL;
|
FUSE_DATA *fuse_data = NULL;
|
||||||
XRDP_INODE *xinode;
|
|
||||||
|
|
||||||
tui32 Length;
|
tui32 Length;
|
||||||
tui64 CreationTime;
|
tui64 CreationTime;
|
||||||
@ -902,6 +949,7 @@ dev_redir_proc_query_dir_response(IRP *irp,
|
|||||||
tui32 FileAttributes;
|
tui32 FileAttributes;
|
||||||
tui32 FileNameLength;
|
tui32 FileNameLength;
|
||||||
tui32 status;
|
tui32 status;
|
||||||
|
struct file_attr fattr;
|
||||||
|
|
||||||
char filename[256];
|
char filename[256];
|
||||||
unsigned int i = 0;
|
unsigned int i = 0;
|
||||||
@ -967,25 +1015,16 @@ dev_redir_proc_query_dir_response(IRP *irp,
|
|||||||
//log_debug("FileNameLength: %d", FileNameLength);
|
//log_debug("FileNameLength: %d", FileNameLength);
|
||||||
log_debug("FileName: %s", filename);
|
log_debug("FileName: %s", filename);
|
||||||
|
|
||||||
xinode = g_new0(struct xrdp_inode, 1);
|
fattr.name = filename;
|
||||||
if (xinode == NULL)
|
fattr.mode = WINDOWS_TO_LINUX_FILE_PERM(FileAttributes);
|
||||||
{
|
fattr.size = (size_t) EndOfFile;
|
||||||
log_error("system out of memory");
|
fattr.atime = WINDOWS_TO_LINUX_TIME(LastAccessTime);
|
||||||
fuse_data = devredir_fuse_data_peek(irp);
|
fattr.mtime = WINDOWS_TO_LINUX_TIME(LastWriteTime);
|
||||||
xfuse_devredir_cb_enum_dir(fuse_data->data_ptr, NULL);
|
fattr.ctime = WINDOWS_TO_LINUX_TIME(CreationTime);
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
strcpy(xinode->name, filename);
|
|
||||||
xinode->size = (size_t) EndOfFile;
|
|
||||||
xinode->mode = WINDOWS_TO_LINUX_FILE_PERM(FileAttributes);
|
|
||||||
xinode->atime = WINDOWS_TO_LINUX_TIME(LastAccessTime);
|
|
||||||
xinode->mtime = WINDOWS_TO_LINUX_TIME(LastWriteTime);
|
|
||||||
xinode->ctime = WINDOWS_TO_LINUX_TIME(CreationTime);
|
|
||||||
|
|
||||||
/* add this entry to xrdp file system */
|
/* add this entry to xrdp file system */
|
||||||
fuse_data = devredir_fuse_data_peek(irp);
|
fuse_data = devredir_fuse_data_peek(irp);
|
||||||
xfuse_devredir_cb_enum_dir(fuse_data->data_ptr, xinode);
|
(void)xfuse_devredir_add_file_or_dir(fuse_data->data_ptr, &fattr);
|
||||||
}
|
}
|
||||||
|
|
||||||
dev_redir_send_drive_dir_request(irp, DeviceId, 0, NULL);
|
dev_redir_send_drive_dir_request(irp, DeviceId, 0, NULL);
|
||||||
@ -1048,6 +1087,78 @@ dev_redir_get_dir_listing(void *fusep, tui32 device_id, const char *path)
|
|||||||
return rval;
|
return rval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FUSE calls this function whenever it wants us to lookup a file or directory
|
||||||
|
*
|
||||||
|
* @param fusep opaque data struct that we just pass back to FUSE when done
|
||||||
|
* @param device_id device_id of the redirected share
|
||||||
|
* @param path the name of the directory containing the file
|
||||||
|
* @param file the filename
|
||||||
|
*
|
||||||
|
* @return 0 on success, -1 on failure
|
||||||
|
*****************************************************************************/
|
||||||
|
|
||||||
|
int
|
||||||
|
dev_redir_lookup_entry(void *fusep, tui32 device_id, const char *dirpath,
|
||||||
|
const char *entry)
|
||||||
|
{
|
||||||
|
tui32 DesiredAccess;
|
||||||
|
tui32 CreateOptions;
|
||||||
|
tui32 CreateDisposition;
|
||||||
|
int rval = -1;
|
||||||
|
IRP *irp;
|
||||||
|
size_t pathlen;
|
||||||
|
|
||||||
|
log_debug("fusep=%p", fusep);
|
||||||
|
|
||||||
|
/* Check the qualified name of the file fits in the IRP */
|
||||||
|
pathlen = strlen(dirpath) + strlen(entry);
|
||||||
|
if (!dev_redir_string_ends_with(dirpath,'/'))
|
||||||
|
{
|
||||||
|
++pathlen;
|
||||||
|
}
|
||||||
|
if (pathlen < sizeof(irp->pathname))
|
||||||
|
{
|
||||||
|
if ((irp = devredir_irp_new()) != NULL)
|
||||||
|
{
|
||||||
|
strcpy(irp->pathname, dirpath);
|
||||||
|
if (!dev_redir_string_ends_with(dirpath, '/'))
|
||||||
|
{
|
||||||
|
strcat(irp->pathname, "/");
|
||||||
|
}
|
||||||
|
strcat(irp->pathname, entry);
|
||||||
|
|
||||||
|
/* convert / to windows compatible \ */
|
||||||
|
devredir_cvt_slash(irp->pathname);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Allocate an IRP to open the file, read the basic attributes,
|
||||||
|
* read the standard attributes, and then close the file
|
||||||
|
*/
|
||||||
|
irp->CompletionId = g_completion_id++;
|
||||||
|
irp->completion_type = CID_LOOKUP_BASIC_ENTRY;
|
||||||
|
irp->DeviceId = device_id;
|
||||||
|
|
||||||
|
devredir_fuse_data_enqueue(irp, fusep);
|
||||||
|
|
||||||
|
DesiredAccess = DA_FILE_READ_ATTRIBUTES | DA_SYNCHRONIZE;
|
||||||
|
CreateOptions = 0x020; /* Same as rmdir or file */
|
||||||
|
CreateDisposition = CD_FILE_OPEN;
|
||||||
|
|
||||||
|
log_debug("lookup for device_id=%d path=%s",
|
||||||
|
device_id, irp->pathname);
|
||||||
|
|
||||||
|
rval = dev_redir_send_drive_create_request(device_id,
|
||||||
|
irp->pathname,
|
||||||
|
DesiredAccess, CreateOptions,
|
||||||
|
CreateDisposition,
|
||||||
|
irp->CompletionId);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return rval;
|
||||||
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
dev_redir_file_open(void *fusep, tui32 device_id, const char *path,
|
dev_redir_file_open(void *fusep, tui32 device_id, const char *path,
|
||||||
int mode, int type, const char *gen_buf)
|
int mode, int type, const char *gen_buf)
|
||||||
@ -1066,7 +1177,7 @@ dev_redir_file_open(void *fusep, tui32 device_id, const char *path,
|
|||||||
if (type & OP_RENAME_FILE)
|
if (type & OP_RENAME_FILE)
|
||||||
{
|
{
|
||||||
irp->completion_type = CID_RENAME_FILE;
|
irp->completion_type = CID_RENAME_FILE;
|
||||||
strncpy(irp->gen_buf, gen_buf, 1023);
|
strncpy(irp->gen.buf, gen_buf, 1023);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -1101,14 +1212,30 @@ dev_redir_file_open(void *fusep, tui32 device_id, const char *path,
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
log_debug("open file in O_RDWR");
|
|
||||||
#if 1
|
#if 1
|
||||||
|
switch(mode & O_ACCMODE)
|
||||||
|
{
|
||||||
|
case O_RDONLY:
|
||||||
|
log_debug("open file in O_RDONLY");
|
||||||
|
DesiredAccess = DA_FILE_READ_DATA | DA_SYNCHRONIZE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case O_WRONLY:
|
||||||
|
log_debug("open file in O_WRONLY");
|
||||||
|
DesiredAccess = DA_FILE_WRITE_DATA | DA_SYNCHRONIZE;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
/*
|
||||||
|
* The access mode could conceivably be invalid here,
|
||||||
|
* but we assume this has been checked by the caller
|
||||||
|
*/
|
||||||
|
log_debug("open file in O_RDWR");
|
||||||
/* without the 0x00000010 rdesktop opens files in */
|
/* without the 0x00000010 rdesktop opens files in */
|
||||||
/* O_RDONLY instead of O_RDWR mode */
|
/* O_RDONLY instead of O_RDWR mode */
|
||||||
if (mode & O_RDWR)
|
DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA |
|
||||||
DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA | DA_SYNCHRONIZE | 0x00000010;
|
DA_SYNCHRONIZE | 0x00000010;
|
||||||
else
|
}
|
||||||
DesiredAccess = DA_FILE_READ_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
|
||||||
@ -1277,7 +1404,7 @@ dev_redir_file_write(void *fusep, tui32 DeviceId, tui32 FileId,
|
|||||||
if ((irp = devredir_irp_find_by_fileid(FileId)) == NULL)
|
if ((irp = devredir_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_write_file(fusep, NULL, 0);
|
xfuse_devredir_cb_write_file(fusep, NT_STATUS_UNSUCCESSFUL, NULL, 0);
|
||||||
xstream_free(s);
|
xstream_free(s);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1286,7 +1413,7 @@ dev_redir_file_write(void *fusep, tui32 DeviceId, tui32 FileId,
|
|||||||
if ((new_irp = devredir_irp_clone(irp)) == NULL)
|
if ((new_irp = devredir_irp_clone(irp)) == NULL)
|
||||||
{
|
{
|
||||||
/* system out of memory */
|
/* system out of memory */
|
||||||
xfuse_devredir_cb_write_file(fusep, NULL, 0);
|
xfuse_devredir_cb_write_file(fusep, NT_STATUS_UNSUCCESSFUL, NULL, 0);
|
||||||
xstream_free(s);
|
xstream_free(s);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
@ -1514,12 +1641,12 @@ devredir_cvt_from_unicode_len(char *path, char *unicode, int len)
|
|||||||
}
|
}
|
||||||
|
|
||||||
int
|
int
|
||||||
dev_redir_string_ends_with(char *string, char c)
|
dev_redir_string_ends_with(const char *string, char c)
|
||||||
{
|
{
|
||||||
int len;
|
size_t len;
|
||||||
|
|
||||||
len = strlen(string);
|
len = strlen(string);
|
||||||
return (string[len - 1] == c) ? 1 : 0;
|
return (len > 0 && string[len - 1] == c) ? 1 : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -1530,7 +1657,7 @@ devredir_insert_RDPDR_header(struct stream *s, tui16 Component,
|
|||||||
xstream_wr_u16_le(s, PacketId);
|
xstream_wr_u16_le(s, PacketId);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
devredir_proc_cid_rmdir_or_file(IRP *irp, tui32 IoStatus)
|
devredir_proc_cid_rmdir_or_file(IRP *irp, tui32 IoStatus)
|
||||||
{
|
{
|
||||||
struct stream *s;
|
struct stream *s;
|
||||||
@ -1567,7 +1694,7 @@ devredir_proc_cid_rmdir_or_file(IRP *irp, tui32 IoStatus)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
devredir_proc_cid_rmdir_or_file_resp(IRP *irp, tui32 IoStatus)
|
devredir_proc_cid_rmdir_or_file_resp(IRP *irp, tui32 IoStatus)
|
||||||
{
|
{
|
||||||
FUSE_DATA *fuse_data;
|
FUSE_DATA *fuse_data;
|
||||||
@ -1594,7 +1721,7 @@ devredir_proc_cid_rmdir_or_file_resp(IRP *irp, tui32 IoStatus)
|
|||||||
IRP_MJ_CLOSE, 0, 32);
|
IRP_MJ_CLOSE, 0, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus)
|
devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus)
|
||||||
{
|
{
|
||||||
struct stream *s;
|
struct stream *s;
|
||||||
@ -1618,7 +1745,7 @@ devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Path in unicode needs this much space */
|
/* Path in unicode needs this much space */
|
||||||
flen = ((g_mbstowcs(NULL, irp->gen_buf, 0) * sizeof(twchar)) / 2) + 2;
|
flen = ((g_mbstowcs(NULL, irp->gen.buf, 0) * sizeof(twchar)) / 2) + 2;
|
||||||
sblen = 6 + flen;
|
sblen = 6 + flen;
|
||||||
|
|
||||||
xstream_new(s, 1024 + flen);
|
xstream_new(s, 1024 + flen);
|
||||||
@ -1636,7 +1763,7 @@ devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus)
|
|||||||
xstream_wr_u32_le(s, flen); /* FileNameLength */
|
xstream_wr_u32_le(s, flen); /* FileNameLength */
|
||||||
|
|
||||||
/* filename in unicode */
|
/* filename in unicode */
|
||||||
devredir_cvt_to_unicode(s->p, irp->gen_buf); /* UNICODE_TODO */
|
devredir_cvt_to_unicode(s->p, irp->gen.buf); /* UNICODE_TODO */
|
||||||
xstream_seek(s, flen);
|
xstream_seek(s, flen);
|
||||||
|
|
||||||
/* send to client */
|
/* send to client */
|
||||||
@ -1647,7 +1774,7 @@ devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus)
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
static void
|
||||||
devredir_proc_cid_rename_file_resp(IRP *irp, tui32 IoStatus)
|
devredir_proc_cid_rename_file_resp(IRP *irp, tui32 IoStatus)
|
||||||
{
|
{
|
||||||
FUSE_DATA *fuse_data;
|
FUSE_DATA *fuse_data;
|
||||||
@ -1675,3 +1802,192 @@ devredir_proc_cid_rename_file_resp(IRP *irp, tui32 IoStatus)
|
|||||||
irp->CompletionId,
|
irp->CompletionId,
|
||||||
IRP_MJ_CLOSE, 0, 32);
|
IRP_MJ_CLOSE, 0, 32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
devredir_proc_cid_lookup_basic_entry(IRP *irp, tui32 IoStatus)
|
||||||
|
{
|
||||||
|
struct stream *s;
|
||||||
|
int bytes;
|
||||||
|
|
||||||
|
if (IoStatus != NT_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
log_debug("lookup returned with IoStatus=0x%08x", IoStatus);
|
||||||
|
|
||||||
|
FUSE_DATA *fuse_data = devredir_fuse_data_dequeue(irp);
|
||||||
|
if (fuse_data)
|
||||||
|
{
|
||||||
|
xfuse_devredir_cb_lookup_entry(fuse_data->data_ptr, IoStatus, NULL);
|
||||||
|
free(fuse_data);
|
||||||
|
}
|
||||||
|
devredir_irp_delete(irp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
xstream_new(s, 1024);
|
||||||
|
|
||||||
|
irp->completion_type = CID_LOOKUP_STD_ENTRY;
|
||||||
|
devredir_insert_DeviceIoRequest(s, irp->DeviceId, irp->FileId,
|
||||||
|
irp->CompletionId,
|
||||||
|
IRP_MJ_QUERY_INFORMATION, 0);
|
||||||
|
|
||||||
|
xstream_wr_u32_le(s, FileBasicInformation);
|
||||||
|
xstream_wr_u32_le(s, FILE_BASIC_INFORMATION_SIZE);
|
||||||
|
/* buffer length */
|
||||||
|
xstream_seek(s, 24); /* padding */
|
||||||
|
xstream_seek(s, FILE_BASIC_INFORMATION_SIZE);
|
||||||
|
/* buffer */
|
||||||
|
/* send to client */
|
||||||
|
bytes = xstream_len(s);
|
||||||
|
send_channel_data(g_rdpdr_chan_id, s->data, bytes);
|
||||||
|
xstream_free(s);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
devredir_proc_cid_lookup_basic_entry_resp(IRP *irp,
|
||||||
|
struct stream *s_in,
|
||||||
|
tui32 IoStatus)
|
||||||
|
{
|
||||||
|
tui32 Length = 0;
|
||||||
|
tui64 CreationTime;
|
||||||
|
tui64 LastAccessTime;
|
||||||
|
tui64 LastWriteTime;
|
||||||
|
tui32 FileAttributes;
|
||||||
|
|
||||||
|
log_debug("basic_lookup returned with IoStatus=0x%08x", IoStatus);
|
||||||
|
|
||||||
|
/* Data as we expect? */
|
||||||
|
if (IoStatus == NT_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
xstream_rd_u32_le(s_in, Length);
|
||||||
|
if (Length != FILE_BASIC_INFORMATION_SIZE)
|
||||||
|
{
|
||||||
|
log_error("Expected FILE_BASIC_OPEN_INFORMATION data but len=%d",
|
||||||
|
Length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (IoStatus != NT_STATUS_SUCCESS ||
|
||||||
|
Length != FILE_BASIC_INFORMATION_SIZE)
|
||||||
|
{
|
||||||
|
/* Return a lookup fail to the FUSE caller */
|
||||||
|
FUSE_DATA *fuse_data = devredir_fuse_data_dequeue(irp);
|
||||||
|
if (fuse_data)
|
||||||
|
{
|
||||||
|
xfuse_devredir_cb_lookup_entry(fuse_data->data_ptr, IoStatus, NULL);
|
||||||
|
free(fuse_data);
|
||||||
|
}
|
||||||
|
devredir_irp_delete(irp);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_debug("processing FILE_BASIC_INFORMATION");
|
||||||
|
|
||||||
|
xstream_rd_u64_le(s_in, CreationTime);
|
||||||
|
xstream_rd_u64_le(s_in, LastAccessTime);
|
||||||
|
xstream_rd_u64_le(s_in, LastWriteTime);
|
||||||
|
xstream_seek(s_in, 8); /* ChangeTime */
|
||||||
|
xstream_rd_u32_le(s_in, FileAttributes);
|
||||||
|
|
||||||
|
//log_debug("CreationTime: 0x%llx",
|
||||||
|
// (unsigned long long)CreationTime);
|
||||||
|
//log_debug("LastAccessTime: 0x%llx",
|
||||||
|
// (unsigned long long)LastAccessTime);
|
||||||
|
//log_debug("LastWriteTime: 0x%llx",
|
||||||
|
// (unsigned long long)LastWriteTime);
|
||||||
|
//log_debug("FileAttributes: 0x%x", (unsigned int)FileAttributes);
|
||||||
|
|
||||||
|
/* Save the basic attributes in the IRP */
|
||||||
|
irp->gen.fattr.mode = WINDOWS_TO_LINUX_FILE_PERM(FileAttributes);
|
||||||
|
irp->gen.fattr.atime = WINDOWS_TO_LINUX_TIME(LastAccessTime);
|
||||||
|
irp->gen.fattr.mtime = WINDOWS_TO_LINUX_TIME(LastWriteTime);
|
||||||
|
irp->gen.fattr.ctime = WINDOWS_TO_LINUX_TIME(CreationTime);
|
||||||
|
|
||||||
|
/* Re-use the IRP to lookup the FileStandardInformation */
|
||||||
|
lookup_std_entry(irp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
lookup_std_entry(IRP *irp)
|
||||||
|
{
|
||||||
|
struct stream *s;
|
||||||
|
int bytes;
|
||||||
|
|
||||||
|
xstream_new(s, 1024);
|
||||||
|
|
||||||
|
irp->completion_type = CID_LOOKUP_ENTRY_RESP;
|
||||||
|
devredir_insert_DeviceIoRequest(s, irp->DeviceId, irp->FileId,
|
||||||
|
irp->CompletionId,
|
||||||
|
IRP_MJ_QUERY_INFORMATION, 0);
|
||||||
|
|
||||||
|
xstream_wr_u32_le(s, FileStandardInformation);
|
||||||
|
xstream_wr_u32_le(s, FILE_STD_INFORMATION_SIZE);
|
||||||
|
/* buffer length */
|
||||||
|
xstream_seek(s, 24); /* padding */
|
||||||
|
xstream_seek(s, FILE_STD_INFORMATION_SIZE);
|
||||||
|
/* buffer */
|
||||||
|
/* send to client */
|
||||||
|
bytes = xstream_len(s);
|
||||||
|
send_channel_data(g_rdpdr_chan_id, s->data, bytes);
|
||||||
|
xstream_free(s);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
devredir_proc_cid_lookup_std_entry_resp(IRP *irp,
|
||||||
|
struct stream *s_in,
|
||||||
|
tui32 DeviceId,
|
||||||
|
tui32 CompletionId,
|
||||||
|
tui32 IoStatus)
|
||||||
|
{
|
||||||
|
FUSE_DATA *fuse_data;
|
||||||
|
tui32 Length;
|
||||||
|
tui64 EndOfFile;
|
||||||
|
struct xrdp_inode *xinode = NULL;
|
||||||
|
|
||||||
|
fuse_data = devredir_fuse_data_dequeue(irp);
|
||||||
|
if (!fuse_data)
|
||||||
|
{
|
||||||
|
log_error("fuse_data unexpectedly NULL!");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (IoStatus == NT_STATUS_SUCCESS)
|
||||||
|
{
|
||||||
|
/* Data as we expect? */
|
||||||
|
xstream_rd_u32_le(s_in, Length);
|
||||||
|
if (Length != FILE_STD_INFORMATION_SIZE)
|
||||||
|
{
|
||||||
|
log_error("Expected FILE_STD_OPEN_INFORMATION data but len=%d",
|
||||||
|
Length);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
log_debug("processing FILE_STD_INFORMATION");
|
||||||
|
xstream_seek(s_in, 8); /* AllocationSize */
|
||||||
|
xstream_rd_u64_le(s_in, EndOfFile);
|
||||||
|
//log_debug("EndOfFile: %lld",
|
||||||
|
// (unsigned long long)EndOfFile);
|
||||||
|
|
||||||
|
/* Finish the attribute block off and add the file */
|
||||||
|
irp->gen.fattr.size = EndOfFile;
|
||||||
|
irp->gen.fattr.name = strrchr(irp->pathname,'\\') + 1;
|
||||||
|
|
||||||
|
xinode = xfuse_devredir_add_file_or_dir(fuse_data->data_ptr,
|
||||||
|
&irp->gen.fattr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
xfuse_devredir_cb_lookup_entry(fuse_data->data_ptr, IoStatus, xinode);
|
||||||
|
free(fuse_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Close the file handle */
|
||||||
|
irp->completion_type = CID_CLOSE;
|
||||||
|
dev_redir_send_drive_close_request(RDPDR_CTYP_CORE,
|
||||||
|
PAKID_CORE_DEVICE_IOREQUEST,
|
||||||
|
irp->DeviceId,
|
||||||
|
irp->FileId,
|
||||||
|
irp->CompletionId,
|
||||||
|
IRP_MJ_CLOSE, 0, 32);
|
||||||
|
}
|
||||||
|
@ -84,19 +84,17 @@ void devredir_insert_DeviceIoRequest(struct stream *s,
|
|||||||
void devredir_cvt_slash(char *path);
|
void devredir_cvt_slash(char *path);
|
||||||
void devredir_cvt_to_unicode(char *unicode, const char *path);
|
void devredir_cvt_to_unicode(char *unicode, const 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(const char *string, char c);
|
||||||
|
|
||||||
void devredir_insert_RDPDR_header(struct stream *s, tui16 Component,
|
void devredir_insert_RDPDR_header(struct stream *s, tui16 Component,
|
||||||
tui16 PacketId);
|
tui16 PacketId);
|
||||||
|
|
||||||
void devredir_proc_cid_rmdir_or_file(IRP *irp, tui32 IoStatus);
|
|
||||||
void devredir_proc_cid_rmdir_or_file_resp(IRP *irp, tui32 IoStatus);
|
|
||||||
void devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus);
|
|
||||||
void devredir_proc_cid_rename_file_resp(IRP *irp, tui32 IoStatus);
|
|
||||||
|
|
||||||
/* called from FUSE module */
|
/* called from FUSE module */
|
||||||
int dev_redir_get_dir_listing(void *fusep, tui32 device_id, const char *path);
|
int dev_redir_get_dir_listing(void *fusep, tui32 device_id, const char *path);
|
||||||
|
|
||||||
|
int dev_redir_lookup_entry(void *fusep, tui32 device_id, const char *dirpath,
|
||||||
|
const char *entry);
|
||||||
|
|
||||||
int dev_redir_file_open(void *fusep, tui32 device_id, const char *path,
|
int dev_redir_file_open(void *fusep, tui32 device_id, const char *path,
|
||||||
int mode, int type, const char *gen_buf);
|
int mode, int type, const char *gen_buf);
|
||||||
|
|
||||||
@ -260,11 +258,15 @@ enum CREATE_OPTIONS
|
|||||||
#define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x00000002
|
#define IRP_MN_NOTIFY_CHANGE_DIRECTORY 0x00000002
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NTSTATUS codes (used by IoStatus)
|
* NTSTATUS codes (used by IoStatus) - see section 2.3 of MS-ERREF
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define NT_STATUS_SUCCESS 0x00000000
|
#define NT_STATUS_SUCCESS 0x00000000
|
||||||
#define NT_STATUS_UNSUCCESSFUL 0xC0000001
|
#define NT_STATUS_UNSUCCESSFUL 0xC0000001
|
||||||
|
#define NT_STATUS_NO_SUCH_FILE 0xC000000F
|
||||||
|
#define NT_STATUS_ACCESS_DENIED 0xC0000022
|
||||||
|
#define NT_STATUS_OBJECT_NAME_INVALID 0xC0000033
|
||||||
|
#define NT_STATUS_OBJECT_NAME_NOT_FOUND 0xC0000034
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* File system ioctl codes
|
* File system ioctl codes
|
||||||
@ -289,12 +291,16 @@ enum COMPLETION_ID
|
|||||||
CID_RMDIR_OR_FILE,
|
CID_RMDIR_OR_FILE,
|
||||||
CID_RMDIR_OR_FILE_RESP,
|
CID_RMDIR_OR_FILE_RESP,
|
||||||
CID_RENAME_FILE,
|
CID_RENAME_FILE,
|
||||||
CID_RENAME_FILE_RESP
|
CID_RENAME_FILE_RESP,
|
||||||
|
CID_LOOKUP_BASIC_ENTRY,
|
||||||
|
CID_LOOKUP_STD_ENTRY,
|
||||||
|
CID_LOOKUP_ENTRY_RESP
|
||||||
};
|
};
|
||||||
|
|
||||||
enum FS_INFORMATION_CLASS
|
enum FS_INFORMATION_CLASS
|
||||||
{
|
{
|
||||||
FileBasicInformation = 0x00000004, /* set atime, mtime, ctime etc */
|
FileBasicInformation = 0x00000004, /* set atime, mtime, ctime etc */
|
||||||
|
FileStandardInformation = 0x00000005, /* Alloc size, EOF #links, etc */
|
||||||
FileEndOfFileInformation = 0x00000014, /* set EOF info */
|
FileEndOfFileInformation = 0x00000014, /* set EOF info */
|
||||||
FileDispositionInformation = 0x0000000D, /* mark a file for deletion */
|
FileDispositionInformation = 0x0000000D, /* mark a file for deletion */
|
||||||
FileRenameInformation = 0x0000000A, /* rename a file */
|
FileRenameInformation = 0x0000000A, /* rename a file */
|
||||||
|
@ -24,6 +24,8 @@
|
|||||||
#ifndef __IRP_H
|
#ifndef __IRP_H
|
||||||
#define __IRP_H
|
#define __IRP_H
|
||||||
|
|
||||||
|
#include "chansrv_fuse.h"
|
||||||
|
|
||||||
typedef struct fuse_data FUSE_DATA;
|
typedef struct fuse_data FUSE_DATA;
|
||||||
struct fuse_data
|
struct fuse_data
|
||||||
{
|
{
|
||||||
@ -42,7 +44,11 @@ struct irp
|
|||||||
tui32 FileId; /* RDP client provided unique number */
|
tui32 FileId; /* RDP client provided unique number */
|
||||||
char completion_type; /* describes I/O type */
|
char completion_type; /* describes I/O type */
|
||||||
char pathname[256]; /* absolute pathname */
|
char pathname[256]; /* absolute pathname */
|
||||||
char gen_buf[1024]; /* for general use */
|
union
|
||||||
|
{
|
||||||
|
char buf[1024]; /* General character data */
|
||||||
|
struct file_attr fattr; /* Used to assemble file attributes */
|
||||||
|
} gen; /* for general use */
|
||||||
int type;
|
int type;
|
||||||
FUSE_DATA *fd_head; /* point to first FUSE opaque object */
|
FUSE_DATA *fd_head; /* point to first FUSE opaque object */
|
||||||
FUSE_DATA *fd_tail; /* point to last FUSE opaque object */
|
FUSE_DATA *fd_tail; /* point to last FUSE opaque object */
|
||||||
|
Loading…
Reference in New Issue
Block a user