summaryrefslogtreecommitdiffstats
path: root/sesman/chansrv
diff options
context:
space:
mode:
authorLaxmikant Rashinkar <LK.Rashinkar@gmail.com>2013-03-24 12:08:55 -0700
committerLaxmikant Rashinkar <LK.Rashinkar@gmail.com>2013-03-24 12:08:55 -0700
commitdebdb031f1e5ffcdab542db1a06e6adde36f2da4 (patch)
tree536d960b2cb46286604d656ecd5decad0821e84b /sesman/chansrv
parent561b263b9141cb56f315d754920bf07e26af7317 (diff)
downloadxrdp-proprietary-debdb031f1e5ffcdab542db1a06e6adde36f2da4.tar.gz
xrdp-proprietary-debdb031f1e5ffcdab542db1a06e6adde36f2da4.zip
o in file system redirection, added support for renaming files and directories
Diffstat (limited to 'sesman/chansrv')
-rw-r--r--sesman/chansrv/chansrv_fuse.c274
-rw-r--r--sesman/chansrv/chansrv_fuse.h1
-rw-r--r--sesman/chansrv/devredir.c245
-rw-r--r--sesman/chansrv/devredir.h16
4 files changed, 448 insertions, 88 deletions
diff --git a/sesman/chansrv/chansrv_fuse.c b/sesman/chansrv/chansrv_fuse.c
index 80d104d6..f22ef9fc 100644
--- a/sesman/chansrv/chansrv_fuse.c
+++ b/sesman/chansrv/chansrv_fuse.c
@@ -30,11 +30,10 @@
* o copying over an existing file does not work
* o are we calling close?
* o need to keep track of open files, reqd during rename
+ * o need to use dir notification for changed files and update xrdp fs
* o fuse ops to support
* o rename (mv)
* o touch does not work
- * o mknod (may not be required if create is correctly implemented)
- * o symlink
* o keep track of lookup_count
* o chmod must work
* o cat >> file is not working
@@ -75,6 +74,7 @@ void xfuse_devredir_cb_read_file(void *vp, char *buf, size_t length) {}
void xfuse_devredir_cb_enum_dir(void *vp, struct xrdp_inode *xinode) {}
void xfuse_devredir_cb_enum_dir_done(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_file_close(void *vp) {}
#else
@@ -115,7 +115,7 @@ void xfuse_devredir_cb_file_close(void *vp) {}
#define LOG_ERROR 0
#define LOG_INFO 1
#define LOG_DEBUG 2
-#define LOG_LEVEL LOG_DEBUG
+#define LOG_LEVEL LOG_ERROR
#define log_error(_params...) \
{ \
@@ -144,6 +144,8 @@ void xfuse_devredir_cb_file_close(void *vp) {}
} \
}
+#define OP_RENAME_FILE 0x01
+
/* the xrdp file system in memory */
struct xrdp_fs
{
@@ -168,8 +170,10 @@ struct xfuse_info
struct fuse_file_info *fi;
fuse_req_t req;
fuse_ino_t inode;
+ fuse_ino_t new_inode;
int invoke_fuse;
char name[1024];
+ char new_name[1024];
tui32 device_id;
int reply_type;
int mode;
@@ -221,12 +225,15 @@ static struct xrdp_inode * xfuse_create_file_in_xrdp_fs(tui32 device_id,
int type);
static int xfuse_does_file_exist(int parent, char *name);
+static int xfuse_delete_file(int parent, char *name);
+static int xfuse_delete_file_with_xinode(XRDP_INODE *xinode);
+static int xfuse_delete_dir_with_xinode(XRDP_INODE *xinode);
/* forward declarations for calls we make into devredir */
int dev_redir_get_dir_listing(void *fusep, tui32 device_id, char *path);
int dev_redir_file_open(void *fusep, tui32 device_id, char *path,
- int mode, int type);
+ int mode, int type, char *gen_buf);
int dev_redir_file_read(void *fusep, tui32 device_id, tui32 FileId,
tui32 Length, tui64 Offset);
@@ -257,6 +264,10 @@ static void xfuse_cb_rmdir(fuse_req_t req, fuse_ino_t parent,
static void xfuse_cb_unlink(fuse_req_t req, fuse_ino_t parent,
const char *name);
+static void xfuse_cb_rename(fuse_req_t req,
+ fuse_ino_t old_parent, const char *old_name,
+ fuse_ino_t new_parent, const char *new_name);
+
/* this is not a callback, but it is used by the above two functions */
static void xfuse_remove_dir_or_file(fuse_req_t req, fuse_ino_t parent,
const char *name, int type);
@@ -370,6 +381,7 @@ int xfuse_init()
g_xfuse_ops.mkdir = xfuse_cb_mkdir;
g_xfuse_ops.rmdir = xfuse_cb_rmdir;
g_xfuse_ops.unlink = xfuse_cb_unlink;
+ g_xfuse_ops.rename = xfuse_cb_rename;
g_xfuse_ops.open = xfuse_cb_open;
g_xfuse_ops.flush = xfuse_cb_flush;
g_xfuse_ops.read = xfuse_cb_read;
@@ -1104,6 +1116,56 @@ static int xfuse_does_file_exist(int parent, char *name)
return 0;
}
+static int xfuse_delete_file(int parent, char *name)
+{
+ return -1;
+}
+
+static int xfuse_delete_file_with_xinode(XRDP_INODE *xinode)
+{
+ /* make sure it is not a dir */
+ if ((xinode == NULL) || (xinode->mode & S_IFDIR))
+ return -1;
+
+ g_xrdp_fs.inode_table[xinode->parent_inode]->nentries--;
+ g_xrdp_fs.inode_table[xinode->inode] = NULL;
+ free(xinode);
+
+ return 0;
+}
+
+static int xfuse_delete_dir_with_xinode(XRDP_INODE *xinode)
+{
+ XRDP_INODE *xip;
+ int i;
+
+ /* make sure it is not a file */
+ if ((xinode == NULL) || (xinode->mode & S_IFREG))
+ return -1;
+
+ for (i = FIRST_INODE; i < g_xrdp_fs.num_entries; i++)
+ {
+ if ((xip = g_xrdp_fs.inode_table[i]) == NULL)
+ continue;
+
+ /* look for child inodes */
+ if (xip->parent_inode == xinode->inode)
+ {
+ /* got one, delete it */
+ g_xrdp_fs.inode_table[xip->inode] = NULL;
+ free(xip);
+ }
+ }
+
+ /* our parent will have one less dir */
+ g_xrdp_fs.inode_table[xinode->parent_inode]->nentries--;
+
+ g_xrdp_fs.inode_table[xinode->inode] = NULL;
+ free(xinode);
+
+ return 0;
+}
+
/******************************************************************************
** **
** callbacks for devredir **
@@ -1421,6 +1483,64 @@ void xfuse_devredir_cb_rmdir_or_file(void *vp, tui32 IoStatus)
free(fip);
}
+void xfuse_devredir_cb_rename_file(void *vp, tui32 IoStatus)
+{
+ XFUSE_INFO *fip;
+ XRDP_INODE *old_xinode;
+ XRDP_INODE *new_xinode;
+
+ fip = (XFUSE_INFO *) vp;
+ if (fip == NULL)
+ return;
+
+ if (IoStatus != 0)
+ {
+ fuse_reply_err(fip->req, EEXIST);
+ free(fip);
+ return;
+ }
+
+ /*
+ * update xrdp file system
+ */
+
+ /* if destination dir/file exists, delete it */
+ if (xfuse_does_file_exist(fip->new_inode, fip->new_name))
+ {
+ new_xinode = xfuse_get_inode_from_pinode_name(fip->new_inode,
+ fip->new_name);
+
+ if (new_xinode->mode & S_IFREG)
+ xfuse_delete_file_with_xinode(new_xinode);
+ else
+ xfuse_delete_dir_with_xinode(new_xinode);
+
+ new_xinode = NULL;
+ }
+
+ old_xinode = xfuse_get_inode_from_pinode_name(fip->inode, fip->name);
+ if (old_xinode == NULL)
+ {
+ fuse_reply_err(fip->req, EBADF);
+ free(fip);
+ return;
+ }
+
+ old_xinode->parent_inode = fip->new_inode;
+ strcpy(old_xinode->name, fip->new_name);
+
+ if (fip->inode != fip->new_inode)
+ {
+ /* 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->new_inode]->nentries++;
+ }
+
+ fuse_reply_err(fip->req, 0);
+ free(fip);
+}
+
void xfuse_devredir_cb_file_close(void *vp)
{
XFUSE_INFO *fip;
@@ -1864,6 +1984,142 @@ static void xfuse_remove_dir_or_file(fuse_req_t req, fuse_ino_t parent,
}
}
+static void xfuse_cb_rename(fuse_req_t req,
+ fuse_ino_t old_parent, const char *old_name,
+ fuse_ino_t new_parent, const char *new_name)
+{
+ XRDP_INODE *old_xinode;
+ XFUSE_INFO *fip;
+ tui32 new_device_id;
+ char *cptr;
+ char old_full_path[1024];
+ char new_full_path[1024];
+ char *cp;
+
+ tui32 device_id;
+
+ log_debug("entered: old_parent=%d old_name=%s new_parent=%d new_name=%s",
+ old_parent, old_name, new_parent, new_name);
+ xfuse_dump_fs();
+
+ /* is old_parent inode valid? */
+ if (!xfuse_is_inode_valid(old_parent))
+ {
+ log_error("inode %d is not valid", old_parent);
+ fuse_reply_err(req, EINVAL);
+ return;
+ }
+
+ /* is new_parent inode valid? */
+ if (!xfuse_is_inode_valid(new_parent))
+ {
+ log_error("inode %d is not valid", new_parent);
+ fuse_reply_err(req, EINVAL);
+ return;
+ }
+
+ if ((old_name == NULL) || (strlen(old_name) == 0))
+ {
+ fuse_reply_err(req, EINVAL);
+ return;
+ }
+
+ if ((new_name == NULL) || (strlen(new_name) == 0))
+ {
+ fuse_reply_err(req, EINVAL);
+ return;
+ }
+
+ old_xinode = xfuse_get_inode_from_pinode_name(old_parent, old_name);
+ if (old_xinode == NULL)
+ {
+ log_error("did not find file with pinode=%d name=%s",
+ old_parent, old_name);
+ fuse_reply_err(req, EBADF);
+ return;
+ }
+
+ /* if file is open, cannot rename */
+ if (old_xinode->nopen != 0)
+ {
+ fuse_reply_err(req, EBUSY);
+ return;
+ }
+
+ /* rename across file systems not yet supported */
+ new_device_id = xfuse_get_device_id_for_inode(new_parent, new_full_path);
+ strcat(new_full_path, "/");
+ strcat(new_full_path, new_name);
+
+ if (new_device_id != old_xinode->device_id)
+ {
+ log_error("rename across file systems not supported");
+ fuse_reply_err(req, EINVAL);
+ return;
+ }
+
+ if (old_xinode->device_id == 0)
+ {
+ /* specified file is a local resource */
+ log_debug("LK_TODO: this is still a TODO");
+ fuse_reply_err(req, EINVAL);
+ return;
+ }
+
+ /* resource is on a redirected share */
+
+ device_id = old_xinode->device_id;
+
+ xfuse_get_device_id_for_inode(old_parent, old_full_path);
+ strcat(old_full_path, "/");
+ strcat(old_full_path, old_name);
+
+ 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 = old_parent;
+ fip->new_inode = new_parent;
+ strncpy(fip->name, old_name, 1024);
+ strncpy(fip->new_name, new_name, 1024);
+ fip->name[1023] = 0;
+ fip->new_name[1023] = 0;
+ fip->invoke_fuse = 1;
+ fip->device_id = device_id;
+
+ if ((cp = strchr(new_full_path, '/')) == NULL)
+ cp = "\\";
+
+ /* we want path minus 'root node of the share' */
+ if ((cptr = strchr(old_full_path, '/')) == NULL)
+ {
+ /* 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,
+ 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;
+ }
+ }
+}
+
/**
* Create a directory or file
*
@@ -1943,7 +2199,8 @@ static void xfuse_create_dir_or_file(fuse_req_t req, fuse_ino_t parent,
if ((cptr = strchr(full_path, '/')) == NULL)
{
/* get dev_redir to open the remote file */
- if (dev_redir_file_open((void *) fip, device_id, "\\", O_CREAT, type))
+ 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);
@@ -1951,7 +2208,8 @@ static void xfuse_create_dir_or_file(fuse_req_t req, fuse_ino_t parent,
}
else
{
- if (dev_redir_file_open((void *) fip, device_id, cptr, O_CREAT, type))
+ if (dev_redir_file_open((void *) fip, device_id, cptr,
+ O_CREAT, type, NULL))
{
log_error("failed to send dev_redir_get_dir_listing() cmd");
fuse_reply_err(req, EREMOTEIO);
@@ -2021,7 +2279,7 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
{
/* get dev_redir to open the remote file */
if (dev_redir_file_open((void *) fip, device_id, "\\",
- fi->flags, S_IFREG))
+ fi->flags, S_IFREG, NULL))
{
log_error("failed to send dev_redir_open_file() cmd");
fuse_reply_err(req, EREMOTEIO);
@@ -2030,7 +2288,7 @@ static void xfuse_cb_open(fuse_req_t req, fuse_ino_t ino,
else
{
if (dev_redir_file_open((void *) fip, device_id, cptr,
- fi->flags, S_IFREG))
+ fi->flags, S_IFREG, NULL))
{
log_error("failed to send dev_redir_get_dir_listing() cmd");
fuse_reply_err(req, EREMOTEIO);
diff --git a/sesman/chansrv/chansrv_fuse.h b/sesman/chansrv/chansrv_fuse.h
index 00130381..e5dbbdc5 100644
--- a/sesman/chansrv/chansrv_fuse.h
+++ b/sesman/chansrv/chansrv_fuse.h
@@ -58,6 +58,7 @@ void xfuse_devredir_cb_enum_dir_done(void *vp, tui32 IoStatus);
void xfuse_devredir_cb_open_file(void *vp, tui32 DeviceId, tui32 FileId);
void xfuse_devredir_cb_read_file(void *vp, char *buf, size_t length);
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_file_close(void *vp);
#endif
diff --git a/sesman/chansrv/devredir.c b/sesman/chansrv/devredir.c
index 4cd328dc..ea994436 100644
--- a/sesman/chansrv/devredir.c
+++ b/sesman/chansrv/devredir.c
@@ -3,7 +3,7 @@
*
* xrdp device redirection - only drive redirection is currently supported
*
- * Copyright (C) Laxmikant Rashinkar 2013
+ * Copyright (C) Laxmikant Rashinkar 2013 LK.Rashinkar@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -662,87 +662,99 @@ void dev_redir_proc_device_iocompletion(struct stream *s)
switch (irp->completion_type)
{
- case CID_CREATE_DIR_REQ:
- log_debug("got CID_CREATE_DIR_REQ");
- if (IoStatus != NT_STATUS_SUCCESS)
+ case CID_CREATE_DIR_REQ:
+ log_debug("got CID_CREATE_DIR_REQ");
+ if (IoStatus != NT_STATUS_SUCCESS)
+ {
+ /* we were trying to create a request to enumerate a dir */
+ /* that does not exist; let FUSE know */
+ fuse_data = dev_redir_fuse_data_dequeue(irp);
+ if (fuse_data)
{
- /* we were trying to create a request to enumerate a dir */
- /* that does not exist; let FUSE know */
- fuse_data = dev_redir_fuse_data_dequeue(irp);
- if (fuse_data)
- {
- xfuse_devredir_cb_enum_dir_done(fuse_data->data_ptr,
- IoStatus);
- free(fuse_data);
- }
- return;
+ xfuse_devredir_cb_enum_dir_done(fuse_data->data_ptr,
+ IoStatus);
+ free(fuse_data);
}
+ return;
+ }
- stream_rd_u32_le(s, irp->FileId);
- log_debug("got CID_CREATE_DIR_REQ IoStatus=0x%x FileId=%d",
- IoStatus, irp->FileId);
- dev_redir_send_drive_dir_request(irp, DeviceId, 1, irp->pathname);
- break;
+ stream_rd_u32_le(s, irp->FileId);
+ log_debug("got CID_CREATE_DIR_REQ IoStatus=0x%x FileId=%d",
+ IoStatus, irp->FileId);
+ dev_redir_send_drive_dir_request(irp, DeviceId, 1, irp->pathname);
+ break;
- case CID_CREATE_OPEN_REQ:
- stream_rd_u32_le(s, irp->FileId);
- log_debug("got CID_CREATE_OPEN_REQ IoStatus=0x%x FileId=%d",
- IoStatus, irp->FileId);
- fuse_data = dev_redir_fuse_data_dequeue(irp);
- xfuse_devredir_cb_open_file(fuse_data->data_ptr,
- DeviceId, irp->FileId);
- break;
+ case CID_CREATE_OPEN_REQ:
+ stream_rd_u32_le(s, irp->FileId);
+ log_debug("got CID_CREATE_OPEN_REQ IoStatus=0x%x FileId=%d",
+ IoStatus, irp->FileId);
+ fuse_data = dev_redir_fuse_data_dequeue(irp);
+ xfuse_devredir_cb_open_file(fuse_data->data_ptr,
+ DeviceId, irp->FileId);
+ break;
- case CID_READ:
- log_debug("got CID_READ");
- stream_rd_u32_le(s, Length);
- fuse_data = dev_redir_fuse_data_dequeue(irp);
- xfuse_devredir_cb_read_file(fuse_data->data_ptr, s->p, Length);
- break;
+ case CID_READ:
+ log_debug("got CID_READ");
+ stream_rd_u32_le(s, Length);
+ fuse_data = dev_redir_fuse_data_dequeue(irp);
+ xfuse_devredir_cb_read_file(fuse_data->data_ptr, s->p, Length);
+ break;
- case CID_WRITE:
- log_debug("got CID_WRITE");
- stream_rd_u32_le(s, Length);
- fuse_data = dev_redir_fuse_data_dequeue(irp);
- xfuse_devredir_cb_write_file(fuse_data->data_ptr, s->p, Length);
- break;
+ case CID_WRITE:
+ log_debug("got CID_WRITE");
+ stream_rd_u32_le(s, Length);
+ fuse_data = dev_redir_fuse_data_dequeue(irp);
+ xfuse_devredir_cb_write_file(fuse_data->data_ptr, s->p, Length);
+ break;
- case CID_CLOSE:
- log_debug("got CID_CLOSE");
- dev_redir_irp_delete(irp);
- break;
+ case CID_CLOSE:
+ log_debug("got CID_CLOSE");
+ dev_redir_irp_delete(irp);
+ break;
- case CID_FILE_CLOSE:
- log_debug("got CID_FILE_CLOSE");
- fuse_data = dev_redir_fuse_data_dequeue(irp);
- xfuse_devredir_cb_file_close(fuse_data->data_ptr);
- dev_redir_irp_delete(irp);
- break;
+ case CID_FILE_CLOSE:
+ log_debug("got CID_FILE_CLOSE");
+ fuse_data = dev_redir_fuse_data_dequeue(irp);
+ xfuse_devredir_cb_file_close(fuse_data->data_ptr);
+ dev_redir_irp_delete(irp);
+ break;
- case CID_DIRECTORY_CONTROL:
- log_debug("got CID_DIRECTORY_CONTROL");
+ case CID_DIRECTORY_CONTROL:
+ log_debug("got CID_DIRECTORY_CONTROL");
- dev_redir_proc_query_dir_response(irp, s, DeviceId,
- CompletionId, IoStatus);
- break;
+ dev_redir_proc_query_dir_response(irp, s, DeviceId,
+ CompletionId, IoStatus);
+ break;
- case CID_RMDIR_OR_FILE:
- log_debug("got CID_RMDIR_OR_FILE");
- stream_rd_u32_le(s, irp->FileId);
- devredir_proc_cid_rmdir_or_file(irp, IoStatus);
- return;
- break;
+ case CID_RMDIR_OR_FILE:
+ log_debug("got CID_RMDIR_OR_FILE");
+ stream_rd_u32_le(s, irp->FileId);
+ devredir_proc_cid_rmdir_or_file(irp, IoStatus);
+ return;
+ break;
- case CID_RMDIR_OR_FILE_RESP:
- log_debug("got CID_RMDIR_OR_FILE_RESP");
- devredir_proc_cid_rmdir_or_file_resp(irp, IoStatus);
- break;
+ case CID_RMDIR_OR_FILE_RESP:
+ log_debug("got CID_RMDIR_OR_FILE_RESP");
+ devredir_proc_cid_rmdir_or_file_resp(irp, IoStatus);
+ break;
- default:
- log_error("got unknown CompletionID: DeviceId=0x%x "
- "CompletionId=0x%x IoStatus=0x%x",
- DeviceId, CompletionId, IoStatus);
- break;
+ case CID_RENAME_FILE:
+ log_debug("got CID_RENAME_FILE");
+ stream_rd_u32_le(s, irp->FileId);
+ devredir_proc_cid_rename_file(irp, IoStatus);
+ return;
+ break;
+
+ case CID_RENAME_FILE_RESP:
+ log_debug("got CID_RENAME_FILE_RESP");
+ devredir_proc_cid_rename_file_resp(irp, IoStatus);
+ break;
+
+ default:
+ log_error("got unknown CompletionID: DeviceId=0x%x "
+ "CompletionId=0x%x IoStatus=0x%x",
+ DeviceId, CompletionId, IoStatus);
+ break;
}
if (fuse_data)
@@ -898,32 +910,40 @@ int dev_redir_get_dir_listing(void *fusep, tui32 device_id, char *path)
}
int dev_redir_file_open(void *fusep, tui32 device_id, char *path,
- int mode, int type)
+ int mode, int type, char *gen_buf)
{
tui32 DesiredAccess;
tui32 CreateOptions;
- tui32 CreateDisposition;
+ tui32 CreateDisposition;
int rval;
IRP *irp;
log_debug("device_id=%d path=%s mode=0x%x", device_id, path, mode);
- log_debug("O_RDONLY=0x%x O_RDWR=0x%x O_CREAT=0x%x", O_RDONLY, O_RDWR, O_CREAT);
if ((irp = dev_redir_irp_new()) == NULL)
return -1;
+ if (type & OP_RENAME_FILE)
+ {
+ irp->completion_type = CID_RENAME_FILE;
+ strcpy(irp->gen_buf, gen_buf);
+ }
+ else
+ {
+ irp->completion_type = CID_CREATE_OPEN_REQ;
+ }
+
irp->completion_id = g_completion_id++;
- irp->completion_type = CID_CREATE_OPEN_REQ;
irp->device_id = device_id;
strcpy(irp->pathname, path);
dev_redir_fuse_data_enqueue(irp, fusep);
if (mode & O_CREAT)
{
- log_debug("LK_TODO: open file in O_CREAT");
+ log_debug("open file in O_CREAT");
DesiredAccess = DA_FILE_READ_DATA | DA_FILE_WRITE_DATA | DA_SYNCHRONIZE;
- if (type == S_IFDIR)
+ if (type & S_IFDIR)
{
log_debug("creating dir");
CreateOptions = CO_FILE_DIRECTORY_FILE | CO_FILE_SYNCHRONOUS_IO_NONALERT;
@@ -1471,3 +1491,78 @@ void devredir_proc_cid_rmdir_or_file_resp(IRP *irp, tui32 IoStatus)
irp->completion_id,
IRP_MJ_CLOSE, 0, 32);
}
+
+void devredir_proc_cid_rename_file(IRP *irp, tui32 IoStatus)
+{
+ struct stream *s;
+ int bytes;
+ int sblen; /* SetBuffer length */
+ int flen; /*FileNameLength */
+
+
+ if (IoStatus != NT_STATUS_SUCCESS)
+ {
+ FUSE_DATA *fuse_data = dev_redir_fuse_data_dequeue(irp);
+ if (fuse_data)
+ {
+ xfuse_devredir_cb_rename_file(fuse_data->data_ptr, IoStatus);
+ free(fuse_data);
+ }
+ dev_redir_irp_delete(irp);
+ return;
+ }
+
+ stream_new(s, 1024);
+
+ irp->completion_type = CID_RENAME_FILE_RESP;
+ dev_redir_insert_dev_io_req_header(s, irp->device_id, irp->FileId,
+ irp->completion_id,
+ IRP_MJ_SET_INFORMATION, 0);
+
+ flen = strlen(irp->gen_buf) * 2 + 2;
+ sblen = 6 + flen;
+
+ stream_wr_u32_le(s, FileRenameInformation);
+ stream_wr_u32_le(s, sblen); /* Length */
+ stream_seek(s, 24); /* padding */
+ stream_wr_u8(s, 1); /* ReplaceIfExists */
+ stream_wr_u8(s, 0); /* RootDirectory */
+ stream_wr_u32_le(s, flen); /* FileNameLength */
+
+ /* filename in unicode */
+ devredir_cvt_to_unicode(s->p, irp->gen_buf);
+ stream_seek(s, flen);
+
+ /* send to client */
+ bytes = stream_len(s);
+ send_channel_data(g_rdpdr_chan_id, s->data, bytes);
+ stream_free(s);
+
+ return;
+}
+
+void devredir_proc_cid_rename_file_resp(IRP *irp, tui32 IoStatus)
+{
+ FUSE_DATA *fuse_data;
+
+ fuse_data = dev_redir_fuse_data_dequeue(irp);
+ if (fuse_data)
+ {
+ xfuse_devredir_cb_rename_file(fuse_data->data_ptr, IoStatus);
+ free(fuse_data);
+ }
+
+ if (IoStatus != NT_STATUS_SUCCESS)
+ {
+ dev_redir_irp_delete(irp);
+ return;
+ }
+
+ irp->completion_type = CID_CLOSE;
+ dev_redir_send_drive_close_request(RDPDR_CTYP_CORE,
+ PAKID_CORE_DEVICE_IOREQUEST,
+ irp->device_id,
+ irp->FileId,
+ irp->completion_id,
+ IRP_MJ_CLOSE, 0, 32);
+}
diff --git a/sesman/chansrv/devredir.h b/sesman/chansrv/devredir.h
index a4699dcd..8f9975d8 100644
--- a/sesman/chansrv/devredir.h
+++ b/sesman/chansrv/devredir.h
@@ -3,7 +3,7 @@
*
* xrdp device redirection - we mainly use it for drive redirection
*
- * Copyright (C) Laxmikant Rashinkar 2013
+ * Copyright (C) Laxmikant Rashinkar 2013 LK.Rashinkar@gmail.com
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -53,8 +53,8 @@ struct irp
tui32 completion_id; /* unique number */
char completion_type; /* describes I/O type */
tui32 FileId; /* RDP client provided unique number */
- //void *fusep; /* opaque FUSE info */
char pathname[256]; /* absolute pathname */
+ char gen_buf[1024]; /* for general use */
tui32 device_id; /* identifies remote device */
FUSE_DATA *fd_head; /* point to first FUSE opaque object */
FUSE_DATA *fd_tail; /* point to last FUSE opaque object */
@@ -131,12 +131,14 @@ void dev_redir_insert_rdpdr_header(struct stream *s, tui16 Component,
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 */
int dev_redir_get_dir_listing(void *fusep, tui32 device_id, char *path);
int dev_redir_file_open(void *fusep, tui32 device_id, char *path,
- int mode, int type);
+ int mode, int type, char *gen_buf);
int devredir_file_close(void *fusep, tui32 device_id, tui32 file_id);
@@ -149,7 +151,7 @@ int dev_redir_file_read(void *fusep, tui32 device_id, tui32 FileId,
#define LOG_DEBUG 2
#ifndef LOG_LEVEL
-#define LOG_LEVEL LOG_DEBUG
+#define LOG_LEVEL LOG_ERROR
#endif
#define log_error(_params...) \
@@ -356,7 +358,9 @@ enum COMPLETION_ID
CID_CLOSE,
CID_FILE_CLOSE,
CID_RMDIR_OR_FILE,
- CID_RMDIR_OR_FILE_RESP
+ CID_RMDIR_OR_FILE_RESP,
+ CID_RENAME_FILE,
+ CID_RENAME_FILE_RESP
};
enum FS_INFORMATION_CLASS
@@ -407,4 +411,6 @@ enum FS_INFORMATION_CLASS
#define EPOCH_DIFF 11644473600LL
#define WINDOWS_TO_LINUX_TIME(_t) ((_t) / 10000000) - EPOCH_DIFF;
+#define OP_RENAME_FILE 0x01
+
#endif