From debdb031f1e5ffcdab542db1a06e6adde36f2da4 Mon Sep 17 00:00:00 2001 From: Laxmikant Rashinkar Date: Sun, 24 Mar 2013 12:08:55 -0700 Subject: o in file system redirection, added support for renaming files and directories --- sesman/chansrv/chansrv_fuse.c | 274 ++++++++++++++++++++++++++++++++++++++++-- sesman/chansrv/chansrv_fuse.h | 1 + sesman/chansrv/devredir.c | 245 +++++++++++++++++++++++++------------ sesman/chansrv/devredir.h | 16 ++- 4 files changed, 448 insertions(+), 88 deletions(-) (limited to 'sesman/chansrv') 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 -- cgit v1.2.1